Innehållsförteckning:

Skicka numerisk data från en Arduino till en annan: 16 steg
Skicka numerisk data från en Arduino till en annan: 16 steg

Video: Skicka numerisk data från en Arduino till en annan: 16 steg

Video: Skicka numerisk data från en Arduino till en annan: 16 steg
Video: #17 Таймер плановой работы DS3231 RTC | Внешний ПЛК Arduino 2024, Juli
Anonim
Skicka numerisk data från en Arduino till en annan
Skicka numerisk data från en Arduino till en annan

Introduktion

av David Palmer, CDIO Tech. vid Aston University.

Behövde du någonsin skicka några nummer från en Arduino till en annan? Denna instruerbara visar hur.

Du kan enkelt testa att det fungerar genom att helt enkelt skriva en rad nummer som du vill skicka på Serial Monitor -terminalen och se siffrorna komma tillbaka på en andra seriell bildskärm ansluten till den andra Arduino. Du kan till och med använda en Bluetooth -länk.

Vad den gör

Två Arduino -program (skisser i Arduino -tal) behöver utvecklas, ett ett masterprogram för att ansluta till värddatorn som kör Arduino Serial Monitor, ett för att fungera som slav för att ta emot det seriella meddelandet från mastern, avkoda det och skicka tillbaka det. Slaven kan eventuellt visa siffrorna som den hanterar på en andra IDE: s seriella bildskärm - om du vill använda den. Det kan hjälpa till att få saker att fungera i första hand och hjälpa dig om du bestämmer dig för att göra några ändringar i programmen för att passa dina egna krav.

Utrustning

  • 2 Arduino
  • 2 USB -kablar
  • lapptrådar (efter behov)
  • 1 PC/bärbar dator laddad med Arduino IDE (tillgänglig som gratis nedladdning från Arduino.cc -webbplatsen)

Steg 1: Konfigurera - Ställ in din maskinvara först

Konfiguration - konfigurera din maskinvara först
Konfiguration - konfigurera din maskinvara först
Konfiguration - konfigurera din maskinvara först
Konfiguration - konfigurera din maskinvara först

Anslut de 2 Arduinos till 2 USB -portar på din dator.

Tips, det är en bra idé att märka dem som M och S (mästare och slav) så att du inte kommer in i en förvirring senare (som visas på de 2 bilderna här.)

Steg 2: Konfigurera - Ställ in din skärm

Inställningar - Ställ in din skärm
Inställningar - Ställ in din skärm

Det bästa är att ställa in din skärm så att du har

  • IDE laddad med masterprogrammet till vänster och
  • det med slaven till höger.

Håll seriemonitorerna för Maser och Slave till vänster och höger också som visas i skärmdumpen här.

Steg 3: Konfigurera Master End, Anslut sedan tillsammans - Del 1

Konfigurera Master End, Anslut sedan tillsammans - Del 1
Konfigurera Master End, Anslut sedan tillsammans - Del 1

När du ställer in din Master End Serial Monitor för att skicka två nummer måste du alltid använda start- och slutet, avgränsare och kommateckenstecken som du ser här.

Du måste nu ansluta de 2 Arduinoerna över serie. Detta görs med två patchtrådar.

Jag använde grönt och gult

  • Ta det gula först, detta måste anslutas till D6 i en Arduino och D7 i den andra
  • Sedan motsatsen för den gröna tråden, D7 på den första och D6 på den andra Arduino.

Alternativt, om du har något tillgängligt som ett par Bluetooth -moduler - som HC -05 - fungerar dessa också för att ge dig exakt samma effekt som trådarna ovan.

Steg 4: Konfigurera Master End, Anslut sedan tillsammans - Del 2

Konfigurera Master End, Anslut sedan tillsammans - Del 2
Konfigurera Master End, Anslut sedan tillsammans - Del 2
Konfigurera Master End, Anslut sedan tillsammans - Del 2
Konfigurera Master End, Anslut sedan tillsammans - Del 2

Vi använder Software Serial -biblioteket. Ytterligare information finns med denna länk

Du kan se den utropad på rad 7 i något av programmen. Den konfigurerar stiften digital 7 och 6 som TX och RX (sändning och mottagning). Så här kommer data att resa ut från Master Arduino genom den gröna tråden in i slaven, och när slavprogrammet i den andra Arduino har avslutat sitt arbete, tillbaka genom den gula tråden. Längst ner i samma illustration (i fönstret Seriell bildskärm) kan du se att data vi överförde nu framgångsrikt har gått runt slingan som beskrivs här och kommit tillbaka till datorn när paret av heltal snyggt separerade.

Steg 5: Översikt över skisser / program - programmets struktur

Översikt över skisser / program - programmets struktur
Översikt över skisser / program - programmets struktur
Översikt över skisser / program - programmets struktur
Översikt över skisser / program - programmets struktur

Layout Liksom i alla Arduino -skisser finns det 3 grundläggande delar:

  • Deklarationerna
  • Upplägget
  • Huvudslingan

Som ofta förekommer har vi här använt oss av en fjärde sektion som är tillägget till "funktioner". Om du inte är bekant med att använda funktioner kan du Google för "Arduino -funktioner" och du hittar förklaringssajter som exemplet i denna länk: www.tutorialspoint.com/arduino/arduino_functions…..

Vi har också använt flikar för att separera programmet till mer hanterbara block.

De tre blocken vi har använt kan ses högst upp i varje illustration av IDE -fönstren ovan:

  • simpleRxTx0330Master
  • allmänning
  • anteckningar

Det här är faktiskt separata filer i programmets mapp, som du kan se i denna Windows Explorer -vy över slavprogrammets filer.

Det finns en mycket bra anledning till varför vi har gjort detta.

  • När vi byggde upp programmet insåg vi att det mesta av programmet för Mästaren var detsamma som för slaven.
  • Vi slutade med att dra in alla gemensamma delar i en flik, som vi därför kallade "vanliga", och sedan varje gång vi hade felsökat en del (testat den och var nöjda med att den fungerade OK) kopierade vi och klistrade in den hela fliken mittemot Master till Slave, eller vice versa.
  • Anteckningsflikarna råkar också vara identiska, eftersom designen är generisk.

Ingen av funktionerna anropas från setup, de kallas alla från loop, så vi har skapat dem efter installationen men före loop.

Steg 6: Top Down Design

Det är en bra idé att designa din skiss med en definition av vad du vill göra.

När du har detta kan du börja göra skissen göra dessa saker. I allmänhet om det finns en detalj som du inte vet hur du gör ännu, gör det bara till en funktion och lämna skapandet av funktionen till senare.

Detta följer den goda designfilosofin, som undervisas i många universitet, kallad CDIO (Om du inte redan känner till den här kan du googla den och hitta webbplatser för att förklara den som: https://www.cdio.org/s.) Detta säger i princip: Starta inte designen innan du har klart konceptet. Starta inte implementeringen förrän du har klart designen. Förvänta dig inte att den ska fungera innan du har klart implementeringen. C först, sedan D, I och O. Vid varje efterföljande steg itererar du (gå tillbaka runt öglan (erna), så när du är nöjd med din första Design loop tillbaka och kontrollera att den fortfarande uppfyller konceptet, och uppdatera C om du behöver. Och så vidare, så även när du har kommit till Operation, gå hela vägen tillbaka till toppen och se igen hur C ser ut nu, sedan D och I, och gör och kolla alla ändras efter behov. Med programmeringsskisser fungerar detta precis samma sak om du designar uppifrån och ner.

Steg 7: Koncept och design - Del 1

Koncept och design - Del 1
Koncept och design - Del 1
Koncept och design - Del 1
Koncept och design - Del 1

Konceptet här ser ut som dispositionskraven som anges på fliken "anteckningar". '

Designen kan se ut som en tidig version av öglan, som matchar fliken anteckningar och kan se ut ungefär som du ser i den här figuren

Se hur jag gillar att börja med att faktiskt CTRL-C kopiera kommentarerna till slingans huvud först och sedan börja fylla i ämnena med kommandon som gör dessa saker.

Detta sammanställer faktiskt OK som du kan se längst ner på skärmen i figuren. Det sträcker sig från CDIO-steg D till I, och när vi utvecklar koden är det en bra idé att fortsätta runt denna D-I-loop.

Nu är det dags att gå ner till nästa steg, det finns en kommentar där som säger att vi ska: // ta emot något från maskinvarans USB, sedan ska vi överföra det till programvarans seriekanal. Vi skriver den här koden för att få det att hända - raderna 133 till 138 som visas här i gul markering

Steg 8: Koncept och design - Del 2

Koncept och design - Del 2
Koncept och design - Del 2
Koncept och design - Del 2
Koncept och design - Del 2

De två första två funktionerna som vi introducerar här är (recv () och tran () för att ta emot från hårdvaruporten och överföra till programvaruporten - därmed kalla dem med de "hw" eller "sw" parametrar som visas.

Utöver dem har vi lagt till ett test på en global variabel som heter newData. Detta är en flagga som vi kommer att sätta in i funktionen "void recv ();". När ett meddelande har mottagits flaggas denna variabel från falsk till sann. Vi gör detta så att vi bara sänder ett meddelande om det har tagits emot (flagga == true) på rad 134. Och när vi har överfört vårt meddelande som är "jobb gjort" så rensar vi tillbaka flaggan till falsk igen på rad 137.

Återigen kan vi kontrollera kompilering (D till I), och den här gången har vi ett "inte deklarerat" felmeddelande (visas). Detta säger oss att vi inte har deklarerat recv (); fungera. Vi planerar att göra detta senare, så bara för nu så att vi kan få en ren kompilering måste vi skapa en dummy- eller platshållarfunktion, som visas nedan.

Återigen kan vi kontrollera kompilering (D till I), och den här gången har vi ytterligare ett "inte deklarerat" felmeddelande för tran (); fungera. Detta behöver en liknande stubbskapande. Återigen kan vi kontrollera kompilering (D till I), och den här gången kommer vi att hitta detta fungerar perfekt; än så länge är allt bra.

Steg 9: Avsluta huvudslingan: A) Mottagning från USB, B) Mottagning från slav Arduino

Avsluta huvudslingan: A) Mottagning från USB, B) Mottagning från slav Arduino
Avsluta huvudslingan: A) Mottagning från USB, B) Mottagning från slav Arduino
Avsluta huvudslingan: A) Mottagning från USB, B) Mottagning från slav Arduino
Avsluta huvudslingan: A) Mottagning från USB, B) Mottagning från slav Arduino

Det finns en sista del som vi har lagt till för att avsluta den här delen, det vill säga att lägga till lite felsökningskod.

Det finns en annan instruerbar på felsökningsskisser som kan hänvisas till för att förstå vad vi har gjort här och varför. Se instruktionsboken "Hur man bygger och testar Arduino -skisser tills de fungerar"

Så dessa felsökningsrader [136-139 visade] läggs till nästa i huvudslingan och, se och se, du kan testa dem i Master-änden genom att göra felsökningsvariabeln sant och kompilera (I), sedan om när du ansluter en Arduino kan du ladda upp, öppna seriemonitorn och se om det som kommer tillbaka till seriemonitorn är som visas här (ser du meddelandet "DEBUG MODE" läggs till?)

Steg 10: Ta emot och hantera data i slaven Arduino

Ta emot och hantera data i slaven Arduino
Ta emot och hantera data i slaven Arduino
Ta emot och hantera data i slaven Arduino
Ta emot och hantera data i slaven Arduino

Mottagning från slav Arduino

Lägg till den nödvändiga koden för den andra kanalen i huvudslingan, programvarans seriella mottagare som visas - rad 149 till 155.

Kan du se att strukturen är löst baserad på vad vi skrev ovan för Master -fallet?

Du kommer också att se att vi får ett kompilatorfel, en annan odeklarerad funktion - den här gången parseData (); - så vi måste göra en stubbe för detta också innan vi kan köra en felfri testkompilering.

Hantera data i Slave Arduino

Lägg till huvudslingkoden som krävs för Arduino om den är konfigurerad som en slavenhet som visas - rad 163 till 174. Kan du se att strukturen på den liknar den för den första kanalen?

Och du borde tycka att den här gången sammanställs helt bra.

Steg 11: Skriv mottagningsfunktionen

Skriv mottagningsfunktionen
Skriv mottagningsfunktionen

Mottagningsfunktionen - void recv (char from) {} - har två huvudjobb.

1 för att ta emot en rad tecken från USB -kanalen och

2 för att ta emot en från Arduino till Arduino -kanalen.

För det första måste vi använda det eftersom det använder Arduino's inbyggda hårdvaru UART, och för det andra med standard Arduino Library: programvara UART.

När vi börjar lägga till kod till en funktion - för att skapa en funktion som gör något, istället för bara en stubbe - måste vi komma ihåg att ta bort eller kommentera stubben som den ersätter. Annars får vi ett kompileringsfel: omdefinition av 'void lrec (char)'.

Försök att få felet och försök sedan med något av ovanstående sätt för att bli av med det.

Börja med en funktion som ser ut som den vi visar här med raderna 75 till 88 i gult.

Nu vet du att du måste prova kompileringsoperationen med kod. Det ger dig ett fel, som de vi hade tidigare, av typen: funktionsnamn som inte deklareras i detta omfång. Vi kommer inledningsvis att behöva ytterligare en stubbe för att låta oss kompilera förbi detta fel, så lägg till en i som tidigare och se till att du nu kan få en kompilering utan fel.

Låt oss nu titta på koden som vi har skrivit för recv () -funktionen.

Det är ganska rent, du kan se användningen av "om" -villkoret för att producera de två delarna av funktionen som nämns ovan.

Koden inuti "sw" -delen och "hw" -delen är av samma form, och jag kommer att beskriva den här.

Den första av raderna i varje fall är början på en stundslinga. Om du inte är bekant med medan kan du leta upp det på Arduino.cc/Reference -webbplatsen för förklaring och exempel. Här väntar vi "medan" den inbyggda "Serial" -funktionen inte har tagit emot några tecken och eftersom newData -variabeln har stängts av (dvs. newData == false condition är sant). Så snart ett tecken - eller mer än ett tecken - tas emot kommer tiden att "släppa igenom" till den andra raden i detta par. Det kommer då att kräva recAstringChar (char); funktion för att hantera det aktuella tecknet. Detta par linjer kommer sedan att växla medan (eller så länge som) det finns några tecken som fortfarande måste tas emot. När de alla är klara stannar medan tillståndet slutar, så att nästa nivå kan sluta, och i sin tur tillåter rec (char); funktion avslutas. Således har ett fullständigt meddelande nu mottagits.

Steg 12: Skriv mottagningsdelsfunktionen - del 1

Skriv mottagningsdelsfunktionen - del 1
Skriv mottagningsdelsfunktionen - del 1
Skriv mottagningsdelsfunktionen - del 1
Skriv mottagningsdelsfunktionen - del 1

Vi måste nu skriva funktionen som kallas recAstringChar (char);. Du ser från kommentaren till rad 50 här högst upp, att dess uppgift är att uppdatera två buffertar med kopior av det inkommande seriemeddelandet. [Det visade sig när jag försökte få allt att fungera att en sak jag lärde mig var att jag behövde två olika buffertar - eller åtminstone det var det enklaste sättet att komma runt några problem, därför utvecklades det till att behöva två buffertar, så Jag har precis gjort dem.] Jag har ringt en buffert: receivedData och den andra: receivedChars.

Buffertarna är globala variabler, så de deklareras på modulnivå, se rad 9 och 10 på den gemensamma fliken. Det finns andra variabler som deklareras inom denna funktion som därför har lokalt omfång- visas i raderna 51-54 här. Detta är inte platsen för att förklara skillnaderna mellan globaler och lokalbefolkningen, men det finns mer information om detta i https://www.arduino.cc/glossary/en/ under Local and Global.

Du kan också ta reda på allt om datatyper och typmodifierare: statiska, booleska, byte, const, char i https://www.arduino.cc/reference/en/#variables, som visas här.

Huvudprogramflödet i denna funktion styrs av if på rad 56 här och motsvarande annat på rad 74. Detta behandlar två scenarier

a) [från rad 74 på] när det mottagna meddelandet börjar. Detta händer när startMarker upptäcks - detta har definierats som tecknet <, varför vi alltid börjar vår sträng med det tecknet när vi testar skissen. Om vi inte gör det kommer ingenting att bearbetas som mottaget, det kommer att ignoreras allt som om vi skriver nonsens vid "Serial Monitor" -tangentbordet.

b) [rad 56 till 73] som tar emot alla andra tecken, oavsett vad de är, men de behandlar tecken först efter att en giltig start har hänt (a '>' har tagits emot som i a) ovan.)

I dessa rader (från 74 till 78) lägger vi det mottagna <i en av buffertarna (receivedData [0]) men inte i den andra. Vi justerar buffertpekaren (variabel: char ndx) för att peka på nästa reservbuffertposition (receivedData [1]) med kommandot post-increment (++) i raden ndx ++;, och vi ställer den pågående flaggan till sann.

Programflödet i denna del av funktionen styrs av if på rad 57 här, och dess motsvarande annat på rad 65. Detta behandlar två scenarier

a) [från rad 65 på] när det mottagna meddelandet är avslutat. Detta händer när endMarker upptäcks - definieras som>, varför varje gång vi testar vår skiss avslutar vi alltid vår sträng med det tecknet. En av sakerna som händer när sluttecknet tas emot är att den globala flaggan (tekniskt variabel) newData är satt som funktionen slutar, så att funktionen som kallade vår delfunktion (den anropande funktionen: recv (char);) kan "veta" att giltig ny data har mottagits komplett.

b) [rad 57 till 64] som tar emot alla andra tecken, vad de än är. Det parkerar dem helt enkelt i rader i båda buffertarna.

Steg 13: Skriv mottagningsunderfunktionen - del 2

Skriv mottagningsdelsfunktionen - del 2
Skriv mottagningsdelsfunktionen - del 2
Skriv mottagningsdelsfunktionen - del 2
Skriv mottagningsdelsfunktionen - del 2

Det kan hjälpa att ge ett exempel på hur de två buffertarna ser ut när de har fyllts. Om vi skulle skriva in enter, skulle bufferten ha tecknen som visas i dem:

Så nu kan du se att vi har en buffert som är exakt alla samma tecken som vi först skrev in, och en buffert som bara har de två värdena och ett separeringskomma. Nu har vi någon kod som kan ta emot de tecken vi skriver in på Serial Monitor-tangentbordet, vi kan gå från CDIO fas I till O, skriva in några strängar och se vad som händer. Ladda upp koden till Master Arduino, öppna Serial Monitor och försök att skriva in något giltigt, till exempel enter. Får du ett eko på skärmen Serial Monitor som det som visas här?

Steg 14: Skriv överförings- och analysfunktionerna

Skriv överförings- och analysfunktionerna
Skriv överförings- och analysfunktionerna
Skriv överförings- och analysfunktionerna
Skriv överförings- och analysfunktionerna

Först för överföringen

Så nu har vi fått en sträng, vi kan skriva sändningsfunktionen: tran (char); att byta ut sin stubbe. Detta gör att vi kan skicka en sträng från Mästaren till slaven Arduino, så se till att båda enheterna är anslutna och anslutna för att testa den här nya funktionen.

Ange den här funktionen som visas här i raderna 117 till 133. Som du känner igen har den två delar, en för att överföra till USB -kanalen (maskinvara UART) och en för att överföra till den andra Arduino (programvara UART.) Detta bör kompilera fel -gratis, och du kan omedelbart ladda upp skissen och se vad som händer. Den här gången kommer jag att skicka. Får du resultatet?

Skärmdumpen är intressant eftersom den mottagna strängen … ska se korrekt ut som tidigare, och den överförda strängen … ska nu se korrekt ut. Observera dock att heltalskonverteringen inte har fungerat. Det finns fortfarande lite mer kod att lägga till för att få det att fungera.

Steg 15: Skriv överförings- och analysfunktionerna

Skriv överförings- och analysfunktionerna
Skriv överförings- och analysfunktionerna
Skriv överförings- och analysfunktionerna
Skriv överförings- och analysfunktionerna

Sedan för analysen

Detta är en kodbit som analyserar den mottagna strängen för att hämta de numeriska delsträngarna och konverterar dem till heltalsvärden. Det är tomrummet parseData (); huvudslingans funktion

Ersätt analysstumpen med koden som visas på raderna 98 - 113. Ladda upp den och låt oss se om problemet vi hade med de två heltalsvärdena nu är åtgärdat. Låt oss försöka.

Ja, det fungerar, som visas, heltalen som hittats är 49 och 98.

Steg 16: Avsluta

Final!
Final!

Dessa data har gått precis runt slingan från datorn genom Master genom slaven och tillbaka via Master igen till datorn igen. Med den färdiga versionen av vanliga uppladdade till både Master- och slavändar, och med felsökningsläge inaktiverat nu, får vi se data som tas emot korrekt i båda ändar som visas här.

Rekommenderad: