Ovládání výstupů - sériová linka

Axamith
Příspěvky: 530
Registrován: 09 srp 2017, 08:17
Reputation: 0
Kontaktovat uživatele:

Re: Ovládání výstupů - sériová linka

Příspěvek od Axamith » 29 pro 2017, 12:10

Odpoledne to testnu :-) Moc díky.

k tomu GND. Od řídící jednotky (garáž) vedou dvě žíly jako sériová linka a dvě jako tvrdý zdroj k napájení ventilů. tak jsem to použil společně k napájení obou Arduin. Mám tam jednu žílu navíc, tak tou mohu spojit společně GND.

P.S.
Napsal jsem Jéžiškovi o knihu Průvodce světem Arduina, tak to postupně pročítám a hledám různé cesty. Je to asi první kniha o programování, která mě tak chytla. Nejde o to, aby to "jen" fungovalo, ale abych to pochopil a uměl příště použít.

Wojta
Příspěvky: 184
Registrován: 22 črc 2017, 16:39
Reputation: 0

Re: Ovládání výstupů - sériová linka

Příspěvek od Wojta » 29 pro 2017, 20:41

Ano, je potřeba mít spojené země přijímacího a vysílacího Arduina. Nemusí být spojené pokud bys používal třeba RS485 ale Arduino má RS232 TTL. Jestli máš ale Arduina napájené stejným zdrojem tak už země spojené máš.

AstroMiK
Příspěvky: 592
Registrován: 08 pro 2017, 19:05
Reputation: 0

Re: Ovládání výstupů - sériová linka

Příspěvek od AstroMiK » 29 pro 2017, 21:23

Axamith má sice obě desky napájené stejným zdrojem, ale střídavým.
Usměrňovače má až na těch deskách.

Axamith
Příspěvky: 530
Registrován: 09 srp 2017, 08:17
Reputation: 0
Kontaktovat uživatele:

Re: Ovládání výstupů - sériová linka

Příspěvek od Axamith » 30 pro 2017, 20:12

Po těžkých bojích, mnoho slepých uličkám, pročítání manuálů k jednotlivým funkcím ... jsem se prokousal k funkčnímu výsledku. Jako vedlejší produkt tohoto snažení je odpálený USB/TTL programátor :(
Mimo jiné mi velmi pomohl AstroMiK a jeho ukázkový kód. Jak jsem postupně pochopil, ani ten nebyl bez chyby, hlavně ten na přijímací straně, ale už to byla cesta, která vedla k cíli. Dále mi hodně pomohl popis knihovny Serial http://docs.uart.cz/docs/serial/

Kód vysílací strany zůstal v podstatě beze změn, pouze jsem původní proměnnou

Kód: Vybrat vše

byte vysilana_hodnota =0;
nahradil hodnotou 99. Hodnota nula (vypnutý stav) se při přepínání vstupů generovala po lince tak trochu náhodně, tak jsem ji nahradil nenulovým číslem, které mě zrovna napadlo.
Takže vypnutý stav = 99
vstup 1 = 100 (99+1)
vstup 2 = 101(99+2)
vstup 3 = 102 (99+3)
vstup 4 = 103 (99+4)
vstup 5 = 104 (99+5)
vstup 6 = 105 (99+6)

Přijímací stranu jsem postupně zcela přepracoval. Je nutné přijímat číslo, pokud to tak potřebuji

Kód: Vybrat vše

while (Serial.available()) { // cteni ser. linky
byte vstup = Serial.parseInt(); // kdyz se na seriovem portu objevi nejaka ciselna data ...
Dále jsem postupně řešil podmínky, výsledný kód se mi jeví jako nevhodnější. Zcela jsem odstranil počítání bytů v bufferu a zaměřil se jen na čísla. připadalo mi to jednodušší a srozumitelnější. Možná jsem objevil Ameriku, ale doposud jsem nevěděl, že do Arduina mohu posílat po ser. lince data přes ser. monitor. Hodně to ulehčuje práci. Tak jsem odladil vysílací i přijímací část samostatně a následně "jen" propojil a ověřil funkčnost. Odstranil jsem oddělené napájení, udělal jedno společné + Rx, Tx.

Vysílací strana:

Kód: Vybrat vše

//prirazeni vstupu k pinu
byte int_1 = 4; //vstup 1
byte int_2 = 3; //vstup 2
byte int_3 = 5; //vstup 3
byte int_4 = 6; //vstup 4
byte int_5 = 7; //vstup 5
byte int_6 = 8; //vstup 6

void setup()
{
  Serial.begin(9600);// rychlost ser. linky
  //definice pinu - vstup
  pinMode(int_1, INPUT_PULLUP);  // Pull-Upy jsem tam pridaval jen kvuli testovani
  pinMode(int_2, INPUT_PULLUP);
  pinMode(int_3, INPUT_PULLUP);
  pinMode(int_4, INPUT_PULLUP);
  pinMode(int_5, INPUT_PULLUP);
  pinMode(int_6, INPUT_PULLUP);
}


void loop(void)
{
  byte vysilana_hodnota = 99;
  // sepnuty kontakt na GND se odesila jako binarni "1"
  if (digitalRead(int_1) == LOW)  vysilana_hodnota += 1;
  if (digitalRead(int_2) == LOW)  vysilana_hodnota += 2;
  if (digitalRead(int_3) == LOW)  vysilana_hodnota += 3;
  if (digitalRead(int_4) == LOW)  vysilana_hodnota += 4;
  if (digitalRead(int_5) == LOW)  vysilana_hodnota += 5;
  if (digitalRead(int_6) == LOW)  vysilana_hodnota += 6;



 // Serial.println(vysilana_hodnota);
  //  Serial.write(vysilana_hodnota);
  delay(1000);  // dostatecne dlouha doba, aby prijimaci Arduino melo cas prijata data zpracovat a nezahltil se mu prijimaci buffer
}

Přijímací strana:

Kód: Vybrat vše

//prirazeni vystupu k pinu
int out_1 = 7; //vystup 1-pin 7
int out_2 = 6; //vystup 2-pin 6
int out_3 = 5; //vystup 3-pin 5
int out_4 = 4; //vystup 4-pin 4
int out_5 = 3; //vystup 5-pin 3
int out_6 = 2; //vystup 6-pin 2

void setup()  {
  //definice vystupu
pinMode(out_1, OUTPUT);
pinMode(out_2, OUTPUT);
pinMode(out_3, OUTPUT);
pinMode(out_4, OUTPUT);
pinMode(out_5, OUTPUT);
pinMode(out_6, OUTPUT);

//reset vystupu
digitalWrite(out_1, HIGH);
digitalWrite(out_2, HIGH);
digitalWrite(out_3, HIGH);
digitalWrite(out_4, HIGH);  
digitalWrite(out_5, HIGH);
digitalWrite(out_6, HIGH);

Serial.begin(9600); //seriova linka
  }

void loop()
  {

   while (Serial.available()) { // cteni ser. linky
byte vstup = Serial.parseInt(); // kdyz se na seriovem portu objevi nejaka ciselna data ...
// Serial.println(vstup); //vypis promenne na ser. monitor

if(vstup == 100){  // vystup 1 ON
digitalWrite(out_1, LOW);
}

if(vstup == 101){  // vystup 2 ON
digitalWrite(out_2, LOW);
}
  
if(vstup == 102){  // vystup 3 ON
digitalWrite(out_3, LOW);
}
 
if(vstup == 103){  // vystup 4 ON
digitalWrite(out_4, LOW);
}
 
if(vstup == 104){  // vystup 5 ON
digitalWrite(out_5, LOW);
}
 
if(vstup == 105){  // vystup 6 ON
digitalWrite(out_6, LOW);
}

 if(vstup == 99) { // vystupy 1-6 OFF
digitalWrite(out_1, HIGH); 
  digitalWrite(out_2, HIGH);
   digitalWrite(out_3, HIGH);
    digitalWrite(out_4, HIGH);
     digitalWrite(out_5, HIGH);
      digitalWrite(out_6, HIGH);
    }
  }
}
Děkuji všem, kdo mě nakopli správným směrem, doufám, že takto podrobný popis někdy někomu také pomůže.

AstroMiK
Příspěvky: 592
Registrován: 08 pro 2017, 19:05
Reputation: 0

Re: Ovládání výstupů - sériová linka

Příspěvek od AstroMiK » 30 pro 2017, 21:05

Jestli jsi přijímal nějaká náhodná čísla při vysílání 0, tak to bude (pravděpodobně) způsobené rušením přenosu.
Není prostě důvod, proč by s číslem 0 měl být problém, ale číslo 99 je v pořádku.

POZOR!
Ten tvůj způsob počítání proměnné "vysilana_hodnota" bude fungovat jen v případě, že bude sepnutý pouze jeden vstupní pin.

Pokud by se někdy stalo, že se ti sepne víc vstupních pinů zároveň, získáš nesmyslné údaje.
Například když se sepne 2. a 3. vstup zároveň, tak se ti komunikací odešle číslo 104 (99 + 2 + 3).
Tohle číslo se na přijímací straně dekóduje tak, že se sepne výstup "out_5".

To už by bylo skoro lepší tu proměnnou nastavovat takto:

Kód: Vybrat vše

  byte vysilana_hodnota = 99;
  if (digitalRead(int_1) == LOW)  vysilana_hodnota = 100;
  if (digitalRead(int_2) == LOW)  vysilana_hodnota = 101;
  if (digitalRead(int_3) == LOW)  vysilana_hodnota = 102;
  if (digitalRead(int_4) == LOW)  vysilana_hodnota = 103;
  if (digitalRead(int_5) == LOW)  vysilana_hodnota = 104;
  if (digitalRead(int_6) == LOW)  vysilana_hodnota = 105;
Pak by se v připadě sepnutí více vstupů zároveň nastavila "vysilana_hodnota" na nejvyšší z těch sepnutých vstupů.
(třeba při sepnutí 2. a 4. vstupu se nastaví proměnná na 103, což se dekóduje na přijímači jako 4. výstup)


V tom mém původním kódu tohle nebezpečí nehrozí.
Tam když se sepne najednou několik vstupů, tak se dají zase jednoduše všechny zpátky rozkódovat na přijímací straně.

Axamith
Příspěvky: 530
Registrován: 09 srp 2017, 08:17
Reputation: 0
Kontaktovat uživatele:

Re: Ovládání výstupů - sériová linka

Příspěvek od Axamith » 31 pro 2017, 10:30

Já budu spínat pouze jeden vstup. Jde o to, že závlaha má několik okruhů a každý jede v jinou dobu (mezera cca 15 minut mezi sepnutími), dělá se to tak kvůli omezení nadměrného odběru vody ze studny a minimalizování kolísání hladiny. Ta závlaha si umí vzít dost vody, takže kolísající hladina by strhávala drobné písky a zanášel by se vrt (doporučení hydrgeologa). I čerpadlo by zřejmě neužilo několik okruhů najednou.
Ano, máš pravdu, bylo by jistější posílat čísla, která svým součtem nebudou odpovídat žádné nastavené hodnotě, tohle určitě upravím.
Ty nuly jsem také spojoval s rušením přenosu. Ještě se na ten tvůj původní kód mrknu, nyní jsem rád, že mi to konečně jede :-)

sup666
Příspěvky: 5
Registrován: 07 led 2018, 01:15
Reputation: 0

Re: Ovládání výstupů - sériová linka

Příspěvek od sup666 » 07 led 2018, 01:40

Čau chlapi. Mam prosbu. Řeším podobnej problem a když jsem zkoušel ovládat výstupy (prozatim jsem dal jen kontrolně zpět komunikaci na terminal) zdrojákem co tu zdílel AstroMik tak se mi to opakuje a celkevě to blbne. tento problém řeším cca už skoro 15h a napsal jsem cca 5 druhu zdrojáku jak řešit tento problém, ale všechny dopadjí stejně na ho....
Zdroják jsem použil místní:

Kód: Vybrat vše

void setup() {
  
  Serial1.begin(9600);

}

void loop(void)
{
  if (Serial1.available())                          // kdyz se na seriovem portu objevi nejaka data ...
  {
    byte hodnota =  Serial1.read();               // ... tak je precti do promenne

    if ( bitRead(hodnota, 0) == 1)              // otestuj nejnizsi bit z prijateho cisla (tlacitko na int_1)
    {
      Serial1.println("1 zap");// tlacitko na int_1 bylo stisknuto
    }


    if ( bitRead(hodnota, 1) == 1)              // otestuj druhy nejnizsi bit z prijateho cisla (tlacitko na int_2)
    {
      Serial1.println("2 zap");// tlacitko na int_2 bylo stisknuto
    }


    if ( bitRead(hodnota, 2) == 1)
    {
      Serial1.println("3 zap"); // tlacitko na int_3 bylo stisknuto
    }


    if ( bitRead(hodnota, 3) == 1)
    {
      Serial1.println("4 zap");// tlacitko na int_4 bylo stisknuto
    }


    if ( bitRead(hodnota, 4) == 1)
    {
      Serial1.println("5 zap");// tlacitko na int_5 bylo stisknuto
    }


    if ( bitRead(hodnota, 5) == 1)              // otestuj nejvyssi (6.) bit z prijateho cisla (tlacitko na int_6)
    {
      Serial1.println("6 zap");// tlacitko na int_6 bylo stisknuto
    }
 }
}

a pošlu na to 000001
tak výpis vypadá takhle a nevim proč.

Kód: Vybrat vše

01:35:57.527 000001 
01:35:58.286 5 zap 
01:35:58.295 6 zap 
01:35:58.305 5 zap 
01:35:58.315 6 zap 
01:35:58.315 5 zap 
01:35:58.322 6 zap 
01:35:58.356 5 zap 
01:35:58.356 6 zap 
01:35:58.360 5 zap 
01:35:58.499 6 zap 
01:35:58.500 1 zap 
01:35:58.501 5 zap 
01:35:58.502 6 zap 
01:35:58.502 1 zap 
01:35:58.502 3 zap 
01:35:58.502 4 zap 
01:35:58.502 2 zap 
01:35:58.502 4 zap 
Děkuji za jakoukoliv radu proč nebo nápad jak to vyřešit

AstroMiK
Příspěvky: 592
Registrován: 08 pro 2017, 19:05
Reputation: 0

Re: Ovládání výstupů - sériová linka

Příspěvek od AstroMiK » 07 led 2018, 05:12

Problém je v tom, že když zadáš ve sériovém terminálu text "000001", tak se ve skutečnosti rozloží na 8 bajtů s těmito ASCII kódy:
48
48
48
48
48
49
13 (CR)
10 (LF)

Když se tyhle čísla v programu převedou do binárního tvaru:
0b110000
0b110000
0b110000
0b110000
0b110000
0b110001
0b001101
0b001010

Tak tam, kde vidíš ty "1", tam ti to hlásí "zap"


Ten program, který jsem tu navrhoval, počítá s tím, že přijme jen 1 bajt a ten pak rozloží na bity.
Buď teda můžeš použít nějaký jiný terminál, ve kterém je možné zadávat čísla desítkově (nebo hexadecimálně),
A nebo musíš mít i to vysílací Arduino, které ale neodesílá hodnotu pomocí obvyklé funkce "Serial.print(číslo)", ale použije"Serial.write(číslo)".

Obrázek terminálu po odeslání hexadecimálního čísla 0x01 je tady:
http://astromik.org/forum/serialterm.gif

Uživatelský avatar
pavel1tu
Příspěvky: 2054
Registrován: 26 říj 2017, 08:28
Reputation: 0
Bydliště: Trutnov
Kontaktovat uživatele:

Re: Ovládání výstupů - sériová linka

Příspěvek od pavel1tu » 07 led 2018, 10:32

Nechápu, že tu vymýšlíš vymyšlené :-D

Jak píše Astromik, to je ideál, a pokud jde o nějaké přeslechy, dodej tomu "paritní bit" na konec - na wiky jistě najdeš co je paritní bit :-)

osobně mezi stanicemi a centrálkou alarmu posílám 14 informaci (abych měl rezervy), mám to rozložené na 2x8bit(7+parita).

- 0101010 je informace
- 10101010 je informace s paritním bytem
- 10101010 je vlastně 170 v desítkové, což je znak "ª" který pošlu po 485 do centrálky :-) (snad)
-na druhé straně to stejně rozložím i s kontrolou paritního bytu ....

je to dost srozumitelné ? Zatím mi to funguje ....

PS:Další možnost, koupíš si destičku, kde je implementován nějaký protokol, třena CANbus a ten šváb to zajistí za tebe, na strarně příjmu ti vždy vypadne ověřený výsledek - paritu a to další zajistí ten šváb .... jo záleží jaký šváb :-D
UNO, NANO, Mikro, PRO mini, DUE, ESP32S2, RPi PICO
Pavel1TU
"Správně napsaný kod lze číst jako knihu"

sup666
Příspěvky: 5
Registrován: 07 led 2018, 01:15
Reputation: 0

Re: Ovládání výstupů - sériová linka

Příspěvek od sup666 » 07 led 2018, 12:33

Čau moc děkuji. To mě mohlo také napadnou :)) , ale abych se přiznal tak tohle co tu řešíme je ještě závislé na aplikaci co dělá kolega, která posílá textový řetězec v podobě 1.1.1.1.1.1.1.1.1. každých 100ms. A kdysi nám na to fugloval zdroják podobný tomuto:

Kód: Vybrat vše

int dopredu;
int dozadu;
int leva;
int prava;
int nahoru;
int dolu;
int magnet;
int svetla;
int klakson;
int blik;
char zahod1;
char zahod2;

void setup() {

  Serial1.begin(9600);

  pinMode (2, INPUT);   // indikace připojení
  pinMode(22, OUTPUT);   // dopredu
  pinMode(24, OUTPUT);    //dozadu
  pinMode(26, OUTPUT);   // leva
  pinMode(28, OUTPUT);    //prava
  pinMode(30, OUTPUT);    //nahoru
  pinMode(32, OUTPUT);    //dolu
  pinMode(34, OUTPUT);    //magnet
  pinMode(36, OUTPUT);    //svetla
  pinMode(38, OUTPUT);    //klakson
  pinMode(40, OUTPUT);    //blik
  
}

void loop() {

  while (Serial1.available()) {
    
    dopredu = Serial1.parseInt();
    dozadu = Serial1.parseInt();
    leva = Serial1.parseInt();
    prava = Serial1.parseInt();
    nahoru = Serial1.parseInt();
    dolu = Serial1.parseInt();
    magnet = Serial1.parseInt();
    svetla = Serial1.parseInt();
    klakson = Serial1.parseInt();

    

    if (dopredu > 0) digitalWrite (22, HIGH); else digitalWrite (22, LOW);
    if (dozadu > 0) digitalWrite (24, HIGH); else digitalWrite (24, LOW);
    if (leva > 0) digitalWrite (26, HIGH); else digitalWrite (26, LOW);
    if (prava > 0) digitalWrite (28, HIGH); else digitalWrite (28, LOW);
    if (nahoru > 0) digitalWrite (30, HIGH); else digitalWrite (30, LOW);
    if (dolu > 0) digitalWrite (32, HIGH); else digitalWrite (32, LOW);
    if (magnet > 0) digitalWrite (34, HIGH); else digitalWrite (34, LOW);
    if (svetla > 0) digitalWrite (36, HIGH); else digitalWrite (36, LOW);
    if (klakson > 0) tone (38, 440, 500);
  }
  delay(100);
}
ale už nemame tu aplikaci a napsala se podobná, která nám ale nefugluje, a proto zkoušíme mnoho podobných variant , ale pořád bez uspěchu.
Mam podezření že zdrojak pro arduino je v pořádku, ale je problém s aplikací. Tedy ještě jednou prosím, zda tam nevidíte nějakou blbost, kterou nevidím . Děkuji

Odpovědět

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 13 hostů