Zbyšek Voda
Vytvořené odpovědi
-
AutorPříspěvky
-
Zbyšek VodaÚčastník
Dobrý den,
nejsem si teď úplně jistý, ale tento modul komunikuje přes sériovou linku, že?On je problém v tom, že nahrávání programu do Arduina probíhá také přes sériovou linku a když je na ní připojeno ještě něco dalšího, bývá problém s tím, že připojená věc ruší komunikaci na lince.
U desky Arduino Mega máte výhodu, že má vícero hardwarových sériových linek (Označené RX0, TX0, RX1, TX1, …). Programování Arduina probíhá přes RX0 a TX0. Probém můžete vyřešit tím, že WiFi Modul připojíte na jinou sériovou linku, než RX0 a TX0. Pak musíte také upravit program, ale to by mělo být jednoduché 🙂
Zbyšek VodaÚčastníkNemáte jiný rozměr vytvářeného pole, než uvádíte v hranatých závorkách?
Podobný error hlásí iint x[2][2] = {{1,2},{2,3},{3,4}};
Když to nepomůže, pošlete kód 🙂
Zbyšek VodaÚčastníkNení zač, ať se daří. Jsem rád, že program funguje 🙂
Zbyšek VodaÚčastníkJe tam více problémů.
Jeden problém je v tzv. scope – česky tuším rozsah platnosti proměnných.
Na začátku si vytvoříte pole diody, které je globální – můžete k němu přistupovat ve všech funkcích. Potom si třeba ve funkci a vytvoříte pole diody, které je pro tuto funkci lokální. A tím zastíníte globální pole diody. Dále dojde k zavolání funkce zobraz(), ale ta nevidí to lokální pole z funkce a, ale globální pole diody definované na začátku.Kdyby se nejednalo o pole, stačilo by odebrat klíčové slovo boolean ve funkcích a pak už by se měnila hodnota globální proměnné. U pole to ale tak jednoduché není, protože nejde napsat ve funkci
diody[3][3] = {{1,1,1},{1,0,1},{1,1,1}};
.Napadají mě dvě cesty, jak to řešit.
První možnost:
Vytvoříte si několik globálních polí, která budou obsahovat požadované sekvence
Třeba:boolean v1[3][3] = {{1,1,1},{1,0,1},{1,1,1}};
a potom v jednotlivých funkcích překopírujete obsah požadovaného pole do pole diody.
memcpy(diody, v1, 9 * sizeof(boolean));
O memcopy viz zde: http://www.cplusplus.com/reference/cstring/memcpy/Druhá možnost:
Funkci zobraz() přidáte parametr typu pole, přes který vždy předáte pole do funkce zobraz. To pak můžete nechat kód tak, jak máte (lokální pole v tomto případě nevadí), jen přidáte zavolání funkce s parametrem pole: zobraz(diody).
Globální pole diody pak můžete zahodit. Tato cesta je asi schůdnějšíZbyšek VodaÚčastníkPošlete celý kód, takhle se nikam neposuneme.
Zbyšek VodaÚčastníkDobrý den, v C název proměnné nezměníte.
Můžete ale udělat dvojrozměrné pole.Místo
boolean dio1[] = {1,1,1}; boolean dio2[] = {1,0,1}; boolean dio3[] = {1,1,1};
zapište
boolean dio[3][3] = {{1,1,1}, {1,0,1}, {1,1,1}}
a potom už můžete indexovat tak, jak jste to zamýšlel:
třeba:dio[j][i]
Zbyšek VodaÚčastníkJestli je to opravdu problém s nepodepsanými ovladači (instalace hlásí „The third-party INF does not contain digital signature information“, nebo něco na ten způsob), tak by mohl pomoci tento postup: http://forum.arduino.cc/index.php/topic,94651.msg727588.html#msg727588
Pokud vím, tak se tento problém objevoval na Win8 a Win10. Vy máte ale Win7, ne?
Zbyšek VodaÚčastníkKdyž chcete vstup pro heslo, tak použijete
<input type="password" ... >
Potom se místo zanků zobrazí hvězdičky.Zbyšek VodaÚčastníkVe článku Programování webových rozhraní pro Arduino je v sekci Ovládání LED napsáno, jak se dá získat data z GET požadavku.
V můžete udělat HTML formulář a zvolit jako metodu přenášení dat právě GET. A potom už je to stejné, jak popisuji ve článku, jen nečtete jeden znak, ale více.
Jak udělat formulář s metodou get je popsáno třeba zde. Jen zaměníte vstup input za textarea.
Zbyšek VodaÚčastníkJsem rád, že se zadařilo 🙂
K tomu zápisu:
const char* json = “{\”TaskName\”:\”Voda\”,\”Temp-voda\”:21.81}”;
V C/C++ se řetězce zapisují třeba takto:
char *s = "Ahoj Karle!";
Kdybyste ale chtěl v rámci řetězce mít znak uvozovek, nemůžete to zapsat takto:
char *s = "Ahoj "Karle!"";
kompilátor by totiž měl při analýze problém a v kódy by se nevyznal.Musíte mu proto pomoct, a to právě napsáním zpětného lomítka před znak uvozovek. Tomuto se říká escapování a je díky němu možné zpasat znaky, které normálně zapsat nelze – třeba i znak s hodnotou 0 zapíšete \0. Dále jsou to třeba znak tabulátor -\t, nový řádek – \n a další – viz https://en.wikipedia.org/wiki/Escape_sequences_in_C.
Zbyšek VodaÚčastníkNení zač, kdyžtak se ozvěte 🙂
K té knihovně je dokumentace zde: https://bblanchon.github.io/ArduinoJson/doc/index.html
popřípadě kdybyste chtěl zabrousit i do kódu, tak mrkněte sem:
https://github.com/bblanchon/ArduinoJson/tree/master/src/ArduinoJson
ale to už je celkem zběsilé.Zbyšek VodaÚčastníkJeště bych doplnil Vojtu.
Funkce client.read() vrátí jeden byte (tedy i znak), který přečte z dat, které klientovi přicházejí. Vy chcete dosáhnout toho, že budete tyto přečtené znaky postupně načítat a někam ukládat.
K tomu se hodí právě pole – to je vyhrazené místo v paměti, ve kterém je možné se pohybovat pomocí indexu, tedy čísla v hranatých závorkách.
Definici pole v kódu máte:
char c[1024];
říká – v paměti bude pole složené z datového typu char a bude mít 1024 položek.Když chcete nastavit hodnotu počátečního znaku pole, provedete to následovně:
c[0] = 30;
popřípadě
c[0] = 'A';
– tímto do pole uložíte znak A (ve skutečnosti jeho číselnou hodnotu v ASCII tabulcePozor, pole v jazyce C jsou indexované od 0, tedy první prvek pole má index 0, druhý 1 a v tomto případě poslední znak má index 1023.
Pomocí cyklu while tedy budete číst znaky přicházející klientu a ukládat je do pole c. Podmínka client.available() platí, dokud jsou nějaké znaky k přečtení. Po každém průchodu navýšíte počitadlo i o jedna, tedy v dalším průchodu budete zapisovat na následující pozici v poli. Dovolil jsem si rozšířit Vojtův návrh:
int i = 0; while (client.available()) { c[i] = client.read(); i++; } c[i] = '\0' Serial.println(c); i = 0;
Na konec načtených dat jsem ještě přidal znak nula. Tímto jsem z načteného pole znaků vytvořil řetězec, tedy text. Řetězce jsou způsob, jak se dá uložit v kódu text. V jazyku C/C++ jsou uložené jako pole znaků, která jsou ukončená znakem nula. Potom funkce jako Serial.println() ví, kdy přestat s vypisováním (vypisují znak po znaku, dokud nenarazí na 0). Je možné, že i ten JSON parser, který používáte vyžaduje na vstupu validní řetězec a ten musí být ukončený nulou.
Také by možná bylo dobré do cyklu přidat podmínku, aby došlo k načtení maximálně 1023 znaků – více by se nevešlo do pole (poslední znak je právě 0). Také by bylo rozumné zvětšit velikost pole.
Napadlo mě, že budete mít ještě asi problém s HTTP hlavičkou. Přijatá data totiž neobsahují pouze JSON, který chcete parsovat, ale také HTTP hlavičku. Ta vypadá třeba takto:
HTTP/1.x 200 OK Transfer-Encoding: chunked Date: Sat, 28 Nov 2009 04:36:25 GMT Server: LiteSpeed Connection: close
Po hlavičce následují dva znaky zalomení řádku a až poté obsah web stránky – ve vašem případě pravděpodobně právě JSON. S tím se taky budete muset vypořádat 🙂
Zbyšek VodaÚčastníkVy přečtete znak pomocí client.read() a uložíte ho na nultý index pole c. Takto ale zapisujete všechny přečtené znaky na index 0. Nechcete spíše ten index posouvat? 🙂
Zbyšek VodaÚčastníkVojta má s tím prostředníkem dobrý postřeh. PHP se tu celkem nabízí.
Mohlo by to fungovat třeba tak, že po připojení ESP ke stránce s PHP skriptem by se tento skript dotázal meteostanice a dostal by JSON s informacemi. Tento JSON by se vhodně přetransformoval (na čtení jsonu je v PHP myslím přímo utilita) a do ESP už by se odeslala data v daleko jednodušší podobě – například „25;-60;1.8“.
Výhodou tohoto řešení je ulehčení zátěže procesoru. Na druhou stranu, pokud jste s PHP nikdy nedělal, asi bych se touto cestou nevydával. Můžou se totiž objevit další problémy.
Na druhou stranu, když říkáte, že programujete ESP a navíc v této poměrně jednoduché aplikaci – asi by mi nevadilo použití té JSON knihovny, kterou využíváte. U Arduina bych váhal, ale ESP má o poznání více výkonu 🙂
Měl jsem na mysli, že by JSON vypadal třeba následovně:
{ "System": { "Build": 145, "Unit": 2, "Uptime": 139, "Free Ram": 26472 }, "Sensors": { "Temp-voda": 50, "WiFi": -60, "spiral": 1.00 } }
Potom by získání jedné hodnoty ze senzoru bylo jednodušší, protože by odpadlo indexování v rámci pole.
Zbyšek VodaÚčastníkPodle JSON je položka „Sensors“ pole, takže vám chybí ještě jedna indexace.
root["Sensors"][0]["Temp-voda"]
Ještě je otázkou, jestli bude pořadí senzorů v poli vždy takovéto, nebo se bude měnit. V tom případě byste musel nějakým způsobem projít celé pole a najít tu položku, která má atribut „Temp-voda“.
Napadá mě jedno zlepšení – nemůžete změnit tvar toho JSON objektu? Takto je to trochu krkolomné. Mohl by vypadat třeba takto a práce s ním by byla jednodušší:
{ ... Sensors: { Temp-voda: 25, WiFi: -60, ... } }
Potom už by přečtení položky Temp-voda vypadalo tak, jak to máte v kódu.
Pokud by přidání indexu nepomohlo, máte ještě možnost projít JSON jen jako text, najít výskyt řetězce – například „Temp-voda“ a potom víte, že za dva znaky začíná hodnota.
Také by možná byla možnost se JSONu úplně vyhnout. Pokud víte, kolik celkem bude senzorů a nepotřebujete jejich počet nějak dynamicky měnit, mohl byste postupovat tak, že si určíte přesné pořadí, v jakém budete hodnoty odesílat a oddělíte je třeba středníkem. Jakmile odešlete všechny hodnoty, tak je zakončíte znakem nového řádku.
Tedy jedna sada měření může vypadat třeba následovně:
25;-60;1.80
a vy budete vědět (předem si určíte), že první hodnota odpovídá teplotě vody, druhá wifi, třetí spiral. Také budete vědět, že první dvě hodnoty jsou typu int, takže he vyčtete funkcí parseInt, třetí float, použijete tedy funkci parseFloat.
Pravděpodobně vám ale JSON chodí někde z webu, takže si tvar vybírat.
Jaký projekt stavíte? 🙂
Zbyšek VodaÚčastníkDobrý den, jak se chyba projevuje?
Píše něco IDE? Nějakou chybovou hlášku?Zbyšek VodaÚčastníkJe to nějaké podivné. Když jsem program znovu zkompiloval, tak vyžaduje signaturu
int wifi_send_pkt_freedom(uint8 *buf, int len,bool sys_seq) (stejná je i v dokumentaci).Tedy buf má být opravdu jenom jednoduché pole. Tak jste to asi i na začátku měl, ale házelo to ten podivný error.
Nakonec se mi povedlo přes chybu dostat zápisem
if (wifi_send_pkt_freedom(packet, packetSize, 0) == -1) {
tak jste to ale asi na začátku měl, tak nevím.Btw. v kódu chybí funkce setup a loop, což se překladači taky nebude líbit.
Takto mi to hlásí jen chyby neexistující loop a setup funkce. https://codepaste.net/us7qgo.
Zbyšek VodaÚčastníkTak zkuste ještě wifi_send_pkt_freedom((uint8_t**)&packet, packetSize, 0)
Zbyšek VodaÚčastníkPoužíváte funkci int wifi_send_pkt_freedom(uint8**, int, bool);
Tato funkce má první parametr ukazatel na ukazatel na uint8. Popřípadě se dá také interpretovat jako pole ukazatelů na hodnoty typu uint8, nebo ukazatel na pole (což asi je případ, který potřebujete).Vy ale této funkci předáváte jenom pole, ale ne ukazatel na pole.
Řekněme, že máte něco jako:byte data[] = {1, 2, 3, 4, ...}; wifi_send_pkt_freedom(data, x, y);
Místo data zkuste zapsat &data, tedy:
wifi_send_pkt_freedom(&data, x, y);
Znak ampersand (&) značí, že chcete získat adresu dané proměnné. Ukazatele jsou vlastně adresy.
Většinou stačí přeložit hlášku:
cannot convert ‘uint8_t* {aka unsigned char*}’ to ‘uint8** {aka unsigned char**}’ for argument ‘1’ to ‘int wifi_send_pkt_freedom(uint8**, int, bool)’
můžete číst jako
Nejde převést uint8_t* na uint8** v prvním argumentu funkce wifi_send_pkt_freedom(uint8**, int, bool)
uint8_t* = ukazatel na typ uint8_t / pole uint8
uint8_t** = ukazatel na ukazatel na uint8_t / pole ukazatelů na uint8_t / ukazatel na pole uint8_tPokud to nepůjde, pošlete sem kód 🙂
Zbyšek VodaÚčastníkNa úvodní stránce je formulář, kam dáte email a přijde vám kniha.
Zbyšek VodaÚčastníkV tom výpisu IDE žádnou chybu nehlásí. Podle čeho soudíte, že program nefunguje?
Když nahrajete blikání LEDkou, tak bliká?
Zbyšek VodaÚčastníkPěknou přednášku o Arduino bootloaderu a jeho modifikacích měl Petr Stehlík na posledním Install Festu – https://www.youtube.com/watch?v=6_1VQvVuFf8&feature=youtu.be&list=PLub6xBWO8gV_t_p-5-J_qU20fkkDtsLjB. Třeba byste se mohl nechat inspirovat 🙂
Zbyšek VodaÚčastníkDobrý den, Honzo,
problémů může být více, musíte poskytnout víc informací.
– jaké webové IDE používáte?
– jakou desku máte (nejlépe s odkazem, odkud jste ji koupil)
– hlásí editor při nahrávání nějakou chybu?Zbyšek VodaÚčastníkV C++ může středník vystupovat i jako prázdný příkaz, takže if (C >= 4); vlastně znamená – když C je větší nebo rovno 4, udělej nic.
{ } označují blok kódu, takže to programu nijak nevadí, ale poté následuje else, které přímo před sebou musí mít if.
Zbyšek VodaÚčastníkMělo by být možné sehnat knihovnu, která umí posílat přímo SQL dotazy do databáze. Viz například http://drcharlesbell.blogspot.cz/2013/04/introducing-mysql-connectorarduino_6.html.
Zbyšek VodaÚčastníkTaké jich mám pár doma a snad všechny v sobě AT firmware měly. Spíše byl problém s rychlostí komunikace. Měl jsem za to, že je tam AT vždy, ale máte asi pravdu, že někdy je Číňan nepředvídatelný.
Zbyšek VodaÚčastníkAno, potom stačí z Arduino programu posílat do ESP tyto AT příkazy přes Serial.println(„“); 🙂
Zbyšek VodaÚčastníkKdyž si necháte to zapojení, které zmiňujete v prvním postu:
ESP8266 –> Arduino Mega ADK
TX –> RX1
RX –> TX1
3V3 –> 3.3V (V Arduinu)
EN –> 3.3V (V Arduinu)
GND –> GND
GPIO0 –> GND,tak si pak do loop() dejte
while(Serial.available()) Serial1.write(Serial.read());
while(Serial1.available() Serial.write(Serial1.read());Toto by mělo přeposílat mezi sériovými porty sdílenými s PC a porty RX1 a TX1. Toto mám ozkoušené (dokonce i na ADK) a dá se tak ESP ovládat.
Ty errory, co vám to píše, jsou způsobené tím, že se nahrávací software nedokáže „zkontaktovat“ s EPS8266. Asi za to může to, co psal Aleš.
Zbyšek VodaÚčastníkPokud vám jde jen o to, abyste přes ESP připojil Arduino k WiFi, tak je ESP z výroby vybaveno firmware, který přijímá přes sériovou linku AT příkazy, přes které jej lze ovládat. Viz http://www.pridopia.co.uk/pi-doc/ESP8266ATCommandsSet.pdf.
Pak není nutné nijak měnit firmware ESP. Na druhou stranu jsou AT příkazy trochu neohrabané. Existují knihovny, které pracují nad AT příkazy, takže vám ulehčí práci při ovládání ESP – viz například https://github.com/itead/ITEADLIB_Arduino_WeeESP8266.
Zbyšek VodaÚčastníkDobrý den, teoreticky by to možné bylo. To, čeho chcete dosáhnout, je použití sériového převodníku Ardina pro naprogramování ESP. Určitě tedy musíte mít připojené ESP na piny RX0 a TX0 (ty jsou pro sériovou linku z PC).
Pak je tam ale další problém. Arduino vám bude do programování „kecat“, protože se i ono bude snažit komunikovat přes sériovou linku. Toto se řešilo tuším rezistorem mezi RST a GND u Arduina, ale bohužel se mi teď nedaří najít podrobnosti. Rezistor by měl dočasně vyřadit Atmegu na Arduinu z provozu, aby se nemíchalo do sériovky.
Asi bych vám doporučil pořídit si převodník USB-Serial. Ušetří vám to spoustu starostí 🙂
-
AutorPříspěvky