Prenos cisla z jednoho arduina na druhy pomoci TX,RX

Kony
Příspěvky: 382
Registrován: 09 dub 2020, 11:43
Reputation: 0

Prenos cisla z jednoho arduina na druhy pomoci TX,RX

Příspěvek od Kony » 28 bře 2021, 21:43

Ahoj,
snazim se pomoci prenosu pres serial prenest data z jedoho arduina na druhy..

nyni se mi povedlo prenest slovo "Hello"

NANO (vysílací )

Kód: Vybrat vše

char mystr[5] = "Hello"; //String data
void setup() {
// Begin the Serial at 9600 Baud
Serial.begin(9600);
}
void loop() {
Serial.write(mystr,5); //Write the serial data
delay(1000);
}
MEGA (prijimaci)

Kód: Vybrat vše

char mystr[10]; //Initialized variable to store recieved data

void setup() {
  // Begin the Serial at 9600 Baud
  Serial.begin(9600);
}

void loop() {
  Serial.readBytes(mystr,5); //Read the serial data and store in var
  Serial.println(mystr); //Print data on Serial Monitor
  delay(1000);
}
ale ja bych potreboval na NANO precist hodnotu z cidla (Int a nebo float) a odeslat to na MEGU, ale to se mi ani zaboha nevede....potrebuji prenest hodnoty mezi 0 - 1000 ale v Int abych s tím mohl nadále pracovat

Uživatelský avatar
gilhad
Příspěvky: 779
Registrován: 07 bře 2018, 11:22
Reputation: 0

Re: Prenos cisla z jednoho arduina na druhy pomoci TX,RX

Příspěvek od gilhad » 28 bře 2021, 22:23

https://www.arduino.cc/reference/en/lan ... es/sizeof/
Prenes celou promennou a hotovo :)

:idea: EDIT: :idea: :!: Takhle to nejde, protoze Serial.write nepochopi vetsi promenne jako pole bytu https://www.arduino.cc/reference/en/lan ... ial/write/

Kód: Vybrat vše

int someVar; // napriklad, nebo pole intu, nebo float, nebo ....
....
Serial.write(someVar,sizeof(someVar)); //Write the serial data
druha strana:

Kód: Vybrat vše

int someVar; // presne stejna definice jako na prvni strane (jmeno promenne se muze lisit)

....
Serial.Read(someVar,sizeof(someVar));//Read the serial data and store in var
Naposledy upravil(a) gilhad dne 28 bře 2021, 22:42, celkem upraveno 1 x.

Kony
Příspěvky: 382
Registrován: 09 dub 2020, 11:43
Reputation: 0

Re: Prenos cisla z jednoho arduina na druhy pomoci TX,RX

Příspěvek od Kony » 28 bře 2021, 22:27

muzu te poprosit o presne zapsani do meho prikladu ????

kde mudu mit na strane NANO treba promenou Int = 498

dekuji moc

zkousim :

Kód: Vybrat vše

int a = 12345; 
void setup() {
// Begin the Serial at 9600 Baud
Serial.begin(9600);
}
void loop() {
Serial.write(a,sizeof(a)); //Write the serial data
delay(1000);
}
ale chybova hlaska :

Kód: Vybrat vše

no matching function for call to 'write(int&, unsigned int)'

Uživatelský avatar
gilhad
Příspěvky: 779
Registrován: 07 bře 2018, 11:22
Reputation: 0

Re: Prenos cisla z jednoho arduina na druhy pomoci TX,RX

Příspěvek od gilhad » 29 bře 2021, 00:15

Oznacil jsem puvodni odpoved jako chybnou, ale nechal ji tam jako vystrazny priklad - nejde to, protoze Serial.write nepochopi vetsi promenne jako pole bytu https://www.arduino.cc/reference/en/lan ... ial/write/

Tohle by snad melo chodit (ale nemam to momentalne jak vyzkouset)
vsimni si, ze pred jmenem promenne mam & (coz mi misto hodnoty promenne da jeji adresu)

Kód: Vybrat vše

void SendSomething(void *value, byte size) {
	uint8_t *p=(uint8_t *)value;
	for(int i=size; i>0; i--, p++) {Serial.write(*p);}
}

void setup() {
	// Begin the Serial at 9600 Baud
	Serial.begin(9600);
}

void loop() {

	int a = 12345; 
	SendSomething(&a,sizeof(a));

	float b=12.345;
	SendSomething(&b,sizeof(b));

	delay(1000);
}


Kód: Vybrat vše

void GetSomething(void *value, byte size) {
	Serial.readBytes((char *)value,size);
}

void setup() {
	// Begin the Serial at 9600 Baud
	Serial.begin(9600);
}

void loop() {

	while (0==Serial.available()) {delay(1);}; // cekam, az neco dorazi
	
	int aaa;
	GetSomething(&aaa,sizeof(aaa));

	float bbb;
	GetSomething(&bbb,sizeof(bbb));
	
	// nejsem si jist, zda je spravne cist data z druheho arduina na Serial a zaroven na ten samy Serial vypisovat nejaky vystup ... spis bych tu cekal Serial2 nebo tak neco podle zapojeni
	  Serial.println(aaa); //Print data on Serial Monitor
	  Serial.println(bbb); //Print data on Serial Monitor

//	delay(1000);	// tohle neni idealni, protoze se ti vlivem ruzne delky prijimani a odesilani ta synchronizace po case rozejde
}

Kony
Příspěvky: 382
Registrován: 09 dub 2020, 11:43
Reputation: 0

Re: Prenos cisla z jednoho arduina na druhy pomoci TX,RX

Příspěvek od Kony » 29 bře 2021, 09:33

Super diky.... vyzkousim.

A co myslim tou poznamkou, ze se to po chvilce rozjede ta synchronizace ???
Lze to teda nejak osetrit ?

ondraN
Příspěvky: 932
Registrován: 08 srp 2019, 20:01
Reputation: 0

Re: Prenos cisla z jednoho arduina na druhy pomoci TX,RX

Příspěvek od ondraN » 29 bře 2021, 11:49

Možná by to bylo, právě kvůli té synchronizaci, řešit jako textový výstup a jako text zracovávat. Pro vyzobání čísel z textu se dají použít funkce parseInt() a parseFloat().
U té synchronizace, představ si, že posíláš long int jako 4 byte. Na druhé straně přijímáš a sestavuješ zpátky do longu. A jeden byte ti vypadne, třeba kvůli rušení. Tak všechny další hodnoty od té chvíle, budou mít jinou hodnotu, protože se budou sestávat z jiných byte. Třeba posílám long pomocí čtyřech byte 1 2 3 4
A1 A2 A3 A4 B1 B2 B3 B4 C1 C2 C3 C4 D1 D2....
pokud třeba B2 vypadne, přijmu prvný long dobře, druhý jako B1 B3 B4 C1, třetí jako C2 C3 C4 D1
Problém je, že neodhalím na přijímací straně chybu, protože nemám informaci, jaký byte k čemu patří.

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

Re: Prenos cisla z jednoho arduina na druhy pomoci TX,RX

Příspěvek od AstroMiK » 29 bře 2021, 11:51

Možná by na vysílací straně stačilo obyčejné "Serial.print(promenna);"
Je jedno, jaký typ proměnné by to byl (INT nebo FLOAT)

A na přijímací straně pak něco takovéhodle:

Kód: Vybrat vše

void loop(void)
  {
    if (Serial.available())                 // kdyz se neco objevi na prijimacim bufferu ...
      {
        delay(10);                          // ... dostatecne dlouha pauza na prijem vsech znaku z cisla do bufferu
        int prijato = Serial.parseInt();    // A z prijateho baliku znaku se bude snazit ziskat celociselnou hodnotu
        while (Serial.available())    Serial.read();      // vymazat zbytek dat z bufferu

      }

.
.
.
.
  }
Pro příjem float hodnoty by se jen změnilo "Serial.parseInt()" na "Serial.parseFloat()".

Uživatelský avatar
kiRRow
Příspěvky: 1152
Registrován: 07 kvě 2019, 07:03
Reputation: 0
Bydliště: Opava

Re: Prenos cisla z jednoho arduina na druhy pomoci TX,RX

Příspěvek od kiRRow » 29 bře 2021, 16:52

Při komunikaci dvou a více zařízení po sériové lince je vždy vhodné si vymyslet komunikační protokol.
Pokud vím, že budu posílat jen číslo jednoho typu - posílal bych pevný daný počet byte a na druhé straně bych pevný daný počet byte očekával. Pošlu prostě 0012 pro hodnotu 12.
Pokud vím, že budu posílat rozdílné informace, použil bych řídící znak pro rozhodnutí co se zbytkem dat má druhá strana provést ... I100 nebo F100.01 ... kdykoliv mi příjde I, tak budu dělat parseInt ... kdykoliv příjde F, budu dělat parseFloat. Pokud ale mám zařízení více a dvě znich posílají float a jedno int, tak musím i zjistit, které z těch dvou mi to posílá, nebo naopak kterému já to poslat chci :) pak už budeš posílat Z1F100.01 - Zařízení 1, přepneš si proměnou .. posílá float, přepneš si operaci ... a parseFloat uložíš do proměnné :)

Uživatelský avatar
gilhad
Příspěvky: 779
Registrován: 07 bře 2018, 11:22
Reputation: 0

Re: Prenos cisla z jednoho arduina na druhy pomoci TX,RX

Příspěvek od gilhad » 30 bře 2021, 23:13

Kony píše:
29 bře 2021, 09:33
A co myslim tou poznamkou, ze se to po chvilce rozjede ta synchronizace ???
Lze to teda nejak osetrit ?
Kdyz mam dva pocitace (Arduina, nebo herni, to je celkem fuk) a kazdy dela neco jineho (a tedy tim stravi jinou dobu) a pak dam obema delay(neco_stejneho), aby pockaly a pak se zase potkaly ve stejnem case, tak se drive nebo pozdeji v tom case proste rozejdou.
Pritom to nemusi byt hned (a vetsinou nebyva), ale ta chyba se muze postupne kumulovat a pak se budes divit, proc ti to (napriklad) priblizne kazdeho 2.5 dne udela nejaky nesmysl - a bude se to blbe ladit, protoze to ladeni ti to bude taky ovlivnovat.

Tady napriklad vysilac jen vysila, prijimac prijima a dela dalsi veci (vypisuje vystup) - to neni moc velky rozdil v case a bude to nejakou dobu prochazet, protoze prijimac prijima na pozadi a plni si buffer a pak to z nej taha. Ale v kazdem pruchodu ten prijimac zacne prijimat o neco pozdeji nez v predchozim a to zpozdeni se bude kumulovat. (Kdybys na kazdy dal jeste LEDku, co se rozsviti, na zacatku loop a pred delay zhasne, tak na prijimaci ta LED bude blikat o maly fous pomaleji, cili po spusteni budou okometricky blikat ve stejnou chvili, po nejake dobe ta na prijimaci uz bude oproti te na vysilaci kus pozadu a postupne se to bude zhorsovat.)

Taky je ten rozdil jeste maly, ale pokud na tom budes stavet neco dalsiho, tak celkem ochotne naroste (treba budes vypisovat ne na Serial, ale na nejake LCD a u nekterych (zvlast nekterych I2C, kde se neprenaci jen ta pismena, ale i vsechny ovladaci signaly mezi nimi, kazdy ve zvlastnim a potvrzenem balicku) ten vypis je relativne pomaly), nebo tam budes ta data zapisovat na SD kartu, kdyz jich bude dost, nebo cokoli jineho. A pak ten rozdil poroste rychleji.

Ze zacatku to nevadi - buffer se naplni, prijimac ho po (cim dal delsi) chvili precte a zpracuje a vypada to OK. Ale buffer je maly a kdyz vnem bude nejen aktualni zprava, ale i ta predchozi a ta pred ni a ... tak po chvili proste narazi na tu svou velikost a bud pretece (a prijdes o data a dalsi cteni ti da neco zmrseneho a nekompletniho), nebo se zastavi a bude cekat na vyprazdneni (a ignorovat nove prichozi zpravy) - a opet podle zakona schvalnosti (delka bufferu neni dobre delitelna delkou zpravy) se to stane uprostred zpravy, konec se zahodi, a pokud se to sejde obzvlast dobre, tak zacnes cist behem prijmu dalsi zpravy, takze zacatek se vyignoruje a pak se tam budou nacitat nejake fragmenty, podle toho, jak se ten buffer bude uvolnovat.

A o nekolik prectenych zprav pozdeji najednou dostanes naprostou haluz a chimeru, kde nebude sedet ani delka zpravy, ani format, ani data nebudou davat smysl.

A protoze nijak nekontrolujes, co vlastne prijimas, tak budes pracovat s naprosto "nahodnymi" daty a nebudes o tom vedet, dokud ti to nezacne delat nekde jinde dalsi haluze - "rozsypany caj" na displaji je jeste to nejmin skodlive - klidne ti binarni polozka pohlavi 0=muz 1=zena najednou bude obsahovat hodnotu 52 a az budes pri scitani do pole soucty[pohlavi] pricitat jednicku, ze jako dalsi kus, tak se to pricte k nahodne polozce v pameti - at uz nejakemu cislu, nebo retezci (obzvlast hezke, pokud to bude zrovna znak konce retezce a po zapocitani "attack chopper" se zmeni v obycejny znak), nebo taky navratova adresa nejake funkce - a pak ti vypocet doslova zabloudi nahodne kamkoli.

----

Proto moje reseni voli jinou strategii
- vysilac vysila kdykoli ho napadne (asi tak kazdou sekundu a kousek), ale ne prilis moc casto, takze prijimac ma sanci to zpracovat.
- prijimac se nepokousi uhodnout, kdy bude vysilac vysilat priste, ale proste ceka, dokud nedorazi nejaka data a pak je zacne zpracovavat.
- - cili pokud bys ve vysilaci ten delay(1000) prepsal treba na delay(500), nebo delay(2000), tak to prijimac nepostrehne a bude i nadale data zpracovavat spravne a vcas. (to je ten while (0==Serial.available()) {delay(1);}; // cekam, az neco dorazi - a jeste lepsi by bylo tam dat jeden takovyhle pred kazde cteni ve tvaru while (sizeof(aaa)>Serial.available()) {delay(1);}; // cekam, az dorazi dost bytu pro cteni aaa nebo tak neco )

----

Navic tak nejak nemam rad prikaz delay(), ktery blokuje procesor a neumozni ten cas vyuzit na neco lepsiho, takze bezne spis nechavam behem "cekani" loop volne cyklovat, aby se daly cist senzory/tlacitka, zpracovavat jine veci a tak podobne.

Jasne ze v takovemto jednoucelovem programu (posilam "Hello" furt dokola a nic jineho) to je celkem fuk, ale takovy program je stejne k nicemu (lepe receno to vetsinou je uvodni pokus k vetsimu projektu, co toho bude delat vic a pak uz to najednou naopak ma smysl resit). Takze bych to odesilani taky resil spis takto ( viz https://www.arduino.cc/en/Tutorial/Buil ... thoutDelay ) :

Kód: Vybrat vše


unsigned long cekani_interval = 1000UL; // UL znamena Unsigned Long konstantu a resi podivne problemy s prevody na int a zpet

// jeden z nasledujicich dvou radku:
unsigned long cekani_od = 0UL; // a poprve se to spusti "cekani_interval" od startu arduina
unsigned long cekani_od = ~cekani_interval; // "sprosty trik" jak posunout zacatek pred nulu o interval a jednicku navrch - takze se to spusti hned, protoze uz v nule "je pozde" - viz https://cs.wikipedia.org/wiki/Dvojkov%C3%BD_dopln%C4%9Bk

void loop() {

	unsigned long ted = millis(); // ulozim aktualni cas, at mam nasledne vsude stejny
	if (ted - cekani_od >= cekani_interval) {  // kdyz jsem cekal uz dost dlouho, tak musim neco udelat
		cekani_od = ted; // dalsi zacatek cekani

		int a = 12345; 
		SendSomething(&a,sizeof(a));

		float b=12.345;
		SendSomething(&b,sizeof(b));
	};
}
s vyhodou, ze mnohem lepe dodrzim ten dany interval, protoze odesilam, zatimco interval uz bezi, ale odesilani je v tom bloku, tak se dokonci i kdyby ten interval byl moc kratky (pak by se vysilalo porad, protoze se to rychleji nestiha)

----

Timto zpusobem muzu mit v loop posilani dat, cteni tlacitek, debouncing, cteni cidel, vypocty a kdovi co dalsiho jeste, a navzajem se to ovlinuje minimalne a nerusi se to a procesor toho stihne mnohem vic "naraz" - a pokud uz je vse hotovo, tak je jedno, zda cykluje beznadejne zavreny v delay, nebo zda porad prochazi loop a kouka, jestli neni nahodou neco pripravene konat.

A jasne ze tohle hraje roli az u trosku vetsi projektu (ktere treba na stisknuti jednoho tlacitka poslou na klavesnici jeden retezec a na stisknuti druheho retezec druhy http://micro-corner.gilhad.cz/blog/Ardu ... ouse3.html , nebo celorocne ctou, reguluji a zaznamenavaji teplotu v akvarku), ale neni to zase tolik prace navic a je lepsi si zvyknout delat to spravne uz od zacatku, nez se zacit preucovat ve chvili, kdy program presahne 100 radek, nebo ma delat veci dve misto jen jedne :D

Uživatelský avatar
gilhad
Příspěvky: 779
Registrován: 07 bře 2018, 11:22
Reputation: 0

Re: Prenos cisla z jednoho arduina na druhy pomoci TX,RX

Příspěvek od gilhad » 30 bře 2021, 23:31

kiRRow píše:
29 bře 2021, 16:52
Při komunikaci dvou a více zařízení po sériové lince je vždy vhodné si vymyslet komunikační protokol.
Protokol se hodi vzdycky, a pokud uz to tady prevadime na znaky a zpet, tak by neskodilo taky pouzit oddelovac (treba strednik, cili posilat "Z1F100.01;" ), ze kdyz se ta interpretace nejakou chybou dostane kam nema (ocekava 'Z1F...' nebo 'Z2I...' a dostane 'U3X..' ) tak proste preskace a ignoruje vstup az k tomu stredniku a pak uz je zase ve znamych vodach - sice ztratila jednu zpravu, ale dalsi uz bere a nebloudi.

A u delsich zprav (obsahujicich vic udaju, retezce a tak) neuskoni ani "magicka hlavicka", napriklad kazdou zpravu zacit "##" a pokud pri cteni nove zpravy tam to "##" neni, tak vim, ze je neco spatne hned a ne az pote, co se v pulce zpravy nejak zamotam (jasne tady ty "Z1" "Z2", "Z3" tuto funkci plni jaksi bokem)

A pokud jde o neco jen trosku vetsiho, tak neuskodi ani kontrolni soucet, kdyby na lince bylo nejake ruseni.

Ono i obycejna (suda/licha) parita toho vychyta dost a pokud se nekde uklad pocet selhani a ten soustavne roste, tak je to upozorneni pro autora, ze je neco docela spatne a je potreba bud udelat lepsi linku, nebo protokol (treba samoopravny a s potvrzovanim) - nebo idealne oboji :)

Pripadne tam postupne narvat cely TCP/IP stack :lol:

Odpovědět

Kdo je online

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