Stap 3: Arduino Code - Details
Opdracht en bericht structuur zoals beschreven in de vorige stap
Seriële Parameters: COM11 8 van 9600 N 1
\r of \n tot eind van de opdrachtregel
Bluetooth is op Pin 0 & 1 @ 9600 snelheid
Commando structuur / / CMD RED| GREEN| GEEL = ON| UITSCHAKELEN
CMD TMAX| SECONDEN = waarde
CMD SECONDS = waarde
CMD STATUS
Status berichtenstructuur
STATUS VAN RED| GREEN| YELLOW| TMIN| TMAX| SECONDS| TEMP| DIJ = waarde
Initialisatie van variabelen die nodig zijn voor temperatuurregeling
zweven maxTemp = 30,0; switch op leidde toen temp > maxTemp
int. maxTempSensor = (int) ((maxTemp/100 +.5) * 204.8);
zweven temperatuur = 0,0;
maxTemp kan later worden gewijzigd, maar het programma moet om te beginnen met een standaardwaarde. maxTempSensor is de conversie van maxTemp naar de 0-1023 bereik geboden door Arduino ADC converter; temperatuur vergelijking zal worden uitgevoerd door een interrupt routine die wij zo snel mogelijk willen: het is efficiënter om direct het gehele getal Pin uitvoer waarde in plaats van de float temperatuur te vergelijken. We willen nog steeds verslag van de temperatuur en het programma wordt het opgeslagen in de variabele met dezelfde naam.
Als u niet bekend bent met de temperatuur conversieformule, kunt u eens een kijkje hier.
maxSeconds kan ook worden veranderd met een opdracht, maar moeten we een standaard
int maxSeconds = 10; Verzend statusbericht elke maxSeconds
Verklaringen van Pin-constanten zijn
Const int ledPin = 13; temperatuur geleid
Const int tempPin = A0; T36 temperatuur sensor analoge invoer pin
Const int led1Pin = 3; Geel
Const int led2Pin = 4; Groen
Const int led3Pin = 5; Rood
Variabelen gebruikt in de interrupt routine en toegankelijk van buiten het
vluchtige int tempVal;
vluchtige int seconden = 0;
vluchtige Boole tempHigh = false;
vluchtige Booleaanse statusReport = false;
Volatile is een bijzonder sleutelwoord dat verhindert dat de compiler bepaalde optimalisaties uitvoeren: alle variabelen die zijn gewijzigd binnen een interrupt routine en ook daarbuiten worden benaderd moeten worden aangegeven als vluchtige om aan te geven dat hun waarde op elk gewenst moment wijzigen kunt en om te controleren of de nieuwste, correct, waarde wordt gelezen uit het geheugen wanneer nodig.
Opdracht string variabelen (ze zal later worden verklaard)
InputString koord = "";
String command = "";
String-waarde = "";
Boole stringComplete = false;
De Setup-functie
VOID Setup {}
Start seriële verbinding
Serial.begin(9600);
Serial.Print ("Max T:");
Serial.Print(maxTemp);
Serial.Print ("Sensor:");
Serial.println(maxTempSensor);
inputString.reserve(50); pinMode (ledPin, OUTPUT); pinMode (led1Pin, OUTPUT);
Command.reserve(50);
Value.reserve(50);
digitalWrite (ledPin, laag);
pinMode (led2Pin, OUTPUT);
pinMode (led3Pin, OUTPUT);
digitalWrite (led1Pin, laag);
digitalWrite (led2Pin, laag);
digitalWrite (led3Pin, laag);
De methode van de reserve van een string wijst het aantal bytes geboden als argument.
De volgende code is nodig voor het initialiseren van de timer-interrupt en zet deze op het vuur elke seconde, het langzaamst die Arduino kan doen; voor gedetailleerde informatie zie hier.
cli(); global interrupts uitschakelen initialiseren van Timer1 voor interrupt @ 1000 msec set vergelijken wedstrijd inschrijven om gewenste timer toets: Sei(); inschakelen van de wereldwijde interrupts
TCCR1A = 0; hele TCCR1A register ingesteld op 0
TCCR1B = 0; hetzelfde voor TCCR1B
OCR1A = 15624; CTC-modus inschakelen:
TCCR1B | = (1 << WGM12);
CS10 en CS12 bits ingesteld voor 1024 prescaler:
TCCR1B | = (1 << CS10);
TCCR1B | = (1 << CS12);
timer vergelijk interrupt inschakelen
TIMSK1 | = (1 << OCIE1A);
}
De timer interrupt routine: wij zijn naam niet wijzigen, maar de inhoud is volledig aanpasbaar.
ISR(TIMER1_COMPA_vect) Als (tempVal > maxTempSensor) {}
{
tempVal = analogRead(tempPin);
digitalWrite (ledPin, hoge);
tempHigh = true;
}
else {}
digitalWrite (ledPin, laag);
tempHigh = false;
}
De waarde van de temperatuur - of, zoals hierboven zijn 0-1023 integer vertegenwoordiging - wordt gelezen van de sensor en wordt vergeleken met de de drempelwaarde: wanneer boven de ingebouwde LED brandt en de tempHigh is ingesteld op waar, anders de LED uitstaat andtempHigh is ingesteld op false.
Als (seconden ++ > = maxSeconds) {}
statusReport = true;
seconden = 0;
}
}
Vergeet niet dat de interrupt wordt afgevuurd elke seconde, maar we willen rapporteren van de status van het systeem minder vaak: de variabele seconden is aan elke iteratie verhoogd totdat zij de waarden tot wanneer het rapport verschuldigd is; Dit zal later in de hoofdlus gebeuren door het controleren van statusReport vlag. In de regel nooit nooit uitvoeren iets zo langzaam persoonsgegevens schrijven aan seriële van binnen een interrupt routine.
De loop-functie interpreteert en voert opdrachten wanneer ontvangen, meldt het dan status als vlag wordt gehesen door timer onderbreken. Om te lezen een tekenreeks uit de seriële buffer, loop is afhankelijk van de serialEvent()-functie die wordt vastgesteld aan het eind: deze routine wordt uitgevoerd tussen elke keer loop wordt uitgevoerd. Het is niet wijd gedocumenteerd en het is waarschijnlijk niet van toepassing op alle Arduino modellen; in ieder geval het is niet moeilijk om te nesten van de inhoud binnen de belangrijkste lus (Zie het einde van thi stap).
void loop {} Als (stringComplete) {}
int intValue = 0;
Serial.println(inputString);
Boole stringOK = false;
Als (inputString.startsWith ("CMD")) {}
inputString = inputString.substring(4);
Eerst controleren we als de ontvangen tekenreeks met 'CMD begint': als zodat we de eerste vier tekens negeren kunnen, anders wij later te een fout verhogen zal.
int pos = inputString.indexOf('=');
Als (pos > -1) {}
opdracht = inputString.substring (0, pos);
waarde = inputString.substring (pos + 1, inputString.length()-1); uittreksel van opdracht tot \n uitgesloten
Er zijn twee soorten opdrachten: die een waarde, waar we vindt "=" de variabele +-waardepaar gescheiden, en die waar de opdracht is een enkele richtlijn (STATUS). Als "=" op pos aanwezig is, wordt de tekenreeks is split in opdracht (linkerdeel) en waarde (rechterdeel), vallen zowel de "=" tussenin en de end-of-line karakter aan het einde.
Als (command.equals("RED")) {/ / rood = ON| UITSCHAKELEN
Value.equals("on")? digitalWrite (led3Pin, HIGH): digitalWrite (led3Pin, laag);
stringOK = true;
}
else if (command.equals("GREEN")) {/ / groen = ON| UITSCHAKELEN
Value.equals("on")? digitalWrite (led2Pin, HIGH): digitalWrite (led2Pin, laag);
stringOK = true;
}
else if (command.equals("YELLOW")) {/ / geel = ON| UITSCHAKELEN
Value.equals("on")? digitalWrite (led1Pin, HIGH): digitalWrite (led1Pin, laag);
stringOK = true;
}
We onderzoeken en uitvoeren van de opdrachten van de LED; Merk op dat de code alleen van waarde ON controleert: als je groen schrijft = ASD het zal worden geïnterpreteerd als groen = OFF. Het is niet perfect, maar het houdt dingen een stuk eenvoudiger. stringOK = true is ingesteld, telkens wanneer een opdracht wordt erkend en uitgevoerd zodat verkeerde opdrachten zal later worden gemarkeerd.
else if (command.equals("TMAX")) {/ / TMAX = waarde
intValue = value.toInt();
als (intValue > 0) {
maxTemp = intValue (float);
maxTempSensor (int) = ((maxTemp/100 +.5) * 204.8);
stringOK = true;
}
}
else if (command.equals("SECONDS")) {/ / seconden = waarde
intValue = value.toInt();
als (intValue > 0) {
maxSeconds = intValue;
stringOK = true;
}
}
Wanneer de waarde moet een getal zijn, moeten we het en test het is echt een getal te converteren. In het geval van MaxTemp berekenen we ook de sensor-waarde zoals uiteengezet in de variabele definitie sectie
} / / pos > -1
else if (inputString.startsWith("STATUS")) {
Serial.print ("STATUS rood =");
Serial.println(digitalRead(led3Pin));
Serial.print ("STATUS groen =");
Serial.println(digitalRead(led2Pin));
Serial.print ("STATUS geel =");
Serial.println(digitalRead(led1Pin));
Serial.print ("STATUS TMAX =");
Serial.println(maxTemp);
Serial.print ("STATUS SECONDS =");
Serial.println(maxSeconds);
Serial.print ("STATUS TEMP =");
Serial.println(Temperature);
Serial.print ("STATUS dij =");
Serial.println(tempHigh);
stringOK = true;
} / / inputString.startsWith("STATUS")
Als opdracht STATUS, output het programma gewoon alle seriële informatie.
} / / inputString.startsWith ("CMD")
stringOK? Serial.println ("commando uitgevoerd"): Serial.println ('Invalid Command');
Signaal als een geldige of ongeldige opdracht is ontvangen.
schakelt u de tekenreeks voor de volgende iteratie
inputString = "";
stringComplete = false;
} / / stringComplete
Variabele huishouding voor de volgende iteratie van de opdracht.
Als (statusReport) {}
temperatuur = (tempVal * 0.0048828125 -.5) * 100;
Serial.print ("STATUS TEMP =");
Serial.println(Temperature);
Serial.print ("STATUS dij =");
Serial.println(tempHigh);
statusReport = false;
}
}
De interrupt routine heeft hees de statusReport vlag, sommige informatie is afgedrukt op seriële als de vlag is uitgeschakeld.
Merk op dat de huidige waarde van de temperatuur op dit punt wordt berekend: daarom, als u de opdracht STATUS tussen het interval statusReport, krijgt u het oude starttype van de temperatuur.
Zoals reeds opgemerkt, serialEvent() treedt op wanneer een nieuwe gegevens komt in de seriële hardware-RX. Deze routine wordt uitgevoerd tussen elke keer loop runs, dus met behulp van vertraging binnen lus reactie kan vertragen. Meerdere bytes aan gegevens kunnen beschikbaar zijn.
ongeldig serialEvent() {}
terwijl (Serial.available()) {}
krijg de nieuwe byte:
char inChar = (char)Serial.read();
Voeg het toe aan de inputString:
inputString += inChar;
Als de binnenkomende karakter een nieuwe regel is of een vervoer opvragen, een markering instellen
Zo kan de hoofdlus verrichten iets dienaangaande:
Als (inChar == '\n' || inChar == '\r') {}
stringComplete = true;
}
}
}
Elke byte is van de seriële leest en toegevoegd aan de tekenreeks ingang tot "\n" of "\r" om te betekenen het einde van de tekenreeks wordt aangetroffen: in dit geval de stringComplete vlag, die wordt gecontroleerd door loop, is ingesteld. Regelterugloop, \r zowel newline, \n, zorgt ervoor dat de code is het kundig voor speurder van het einde van de string van een verscheidenheid van ingangen met inbegrip van andere seriële terminals dan de Arduino IDE seriële Monitor.
Opmerking over Bluetooth en Serial
In vele voorbeelden, met inbegrip van JY-MCU verkoper, kunt u de Bluetooth-module die op verschillende digitale pinnen van de Arduino is aangesloten (bijv. 10 en 11) en toegankelijk via de SoftwareSerial-bibliotheek. Gebaseerd op de resultaten van mijn tests, werkt SoftwareSerial perfect wanneer de module wordt gebruikt voor het verzenden van informatie alleen, maar de Arduino Uno niet snel is genoeg bij het ontvangen van opdrachten. Ik heb niet proberen om de snelheid van de verbinding van de SoftwareSerial (in de voorbeelden wordt vaak ingesteld op 2400bps) omdat de MIT AppInventor app niet lijkt te steunen Bluetooth verbinding snelheidsinstelling.
Met SoftwareSerial, serialEvent() werkt niet: men moet te wijzigen (bijv. mySerialEvent()) en noem het expliciet aan het begin van de loop.