BLUETOOTH-modul (3 / 3 steg)
Steg 3: Kod:-
Seriella parametrar: COM11 9600 8 N 1
\r eller \n att avsluta kommandoraden / / Bluetooth är på stift 0 & 1 @ 9600 hastighet / / kommandot struktur / / CMD RED| GREEN| GUL = ON| OFF / / CMD TMAX| SEKUNDER = värde / / CMD sekunder = värde / / CMD STATUS / / Status meddelande struktur / / STATUS RED| GREEN| YELLOW| TMIN| TMAX| SECONDS| TEMP| LÅR = värde initiering av variabler som behövs för temperatur kontroll float maxTemp = 30,0; slå på ledde när temp > maxTemp int maxTempSensor (int) = ((maxTemp/100 +.5) * 204,8); flyta temperatur = 0,0; maxTemp kan senare ändras, men programmet behöver ett standardvärde till att börja med. maxTempSensor är omvandlingen av maxTemp till 0-1023 utbud som tillhandahålls av Arduino ADC omvandlare; temperaturen jämförelse kommer att utföras av ett avbrott rutin som vi vill så fort som möjligt: det är effektivare att direkt jämföra heltalet Pin produktionen värde i stället för float temperaturen. Vi vill fortfarande att rapportera temperaturen och programmet lagrar det i variabeln med samma namn. Om du inte är bekant med konverteringsformeln temperatur, kan du ta en titt här. maxSeconds kan också ändras med ett kommando men behöver vi en standard int maxSeconds = 10; Skicka statusmeddelande varje maxSeconds deklarationer av Pin konstanter const int ledPin = 13. temperaturen ledde const int tempPin = A0; T36 temperatur sensor analoga ingångsstift const int led1Pin = 3; Gul const int led2Pin = 4; Gröna const int led3Pin = 5; Röd variabler används i rutinen avbrott och tillgängliga från utsidan av det flyktiga int tempVal; flyktiga int sekunder = 0; flyktiga boolean tempHigh = false; flyktiga boolean statusReport = false; Volatile är ett speciella nyckelord som hindrar att kompilatorn utför vissa optimeringar: alla variabler som ändras inom ett avbrott rutin och är också nås utanför det måste deklareras som volatile att signalera att deras värde kan ändra när som helst och för att se Senast, korrekt, värdet avläses minne när det behövs. Kommandot strängvariabler (de kommer att förklaras senare) String inputString = ""; String kommando = ""; Strängvärde = ""; booleska stringComplete = false; Setup() funktionen void setup() {//start seriell anslutning Serial.begin(9600); Serial.Print (Max T:"); Serial.Print(maxTemp); Serial.Print ("Sensor:"); Serial.println(maxTempSensor); inputString.reserve(50); Command.Reserve(50); Value.Reserve(50);
pinMode (ledPin, produktionen); digitalWrite (ledPin, låg);
pinMode (led1Pin, produktionen); pinMode (led2Pin, produktionen); pinMode (led3Pin, produktionen); digitalWrite (led1Pin, låg); digitalWrite (led2Pin, låg); digitalWrite (led3Pin, låg); Metoden reserv i en sträng allokerar antalet byte som anges som argument. Följande kod behövs för att initiera på timer avbryta och ställa in den att skjuta varje sekund, den långsammaste den Arduinoen kan göra; för detaljerad information se här. CLI(); Inaktivera globala avbryter
initiera Timer1 för avbrott @ 1000 MSEK TCCR1A = 0; satt hela TCCR1A register till 0 TCCR1B = 0; samma för TCCR1B
inställd önskad timer greve jämför match register: OCR1A = 15624; Aktivera CTC läge: TCCR1B | = (1 << WGM12); Anger CS10 och CS12 bitar för 1024 prescaler: TCCR1B | = (1 << CS10); TCCR1B | = (1 << CS12); Aktivera timern jämför avbrott: TIMSK1 | = (1 << OCIE1A);
SEI(); aktiverar global avbryter} timer avbrott rutin: vi kan inte byta namn, men innehållet är helt anpassningsbara. ISR(TIMER1_COMPA_vect) {tempVal = analogRead(tempPin);
om (tempVal > maxTempSensor) {digitalWrite (ledPin, hög), tempHigh = true;} annat {digitalWrite (ledPin, låg); tempHigh = false;} Temperaturvärde - eller, som diskuterats ovan sin 0-1023 heltal representation - läses från sensorn och jämförs med den tröskelvärdet: när ovanför inbyggd LED lyser och tempHigh är inställt på true, annars LED avstängd och tempHigh har angetts till false. om (sekunder ++ > = maxSeconds) {statusReport = true; sekunder = 0;}} Kom ihåg att avbrottet avfyras varje sekund, men vi vill rapportera systemets status mindre ofta: sekunder variabeln ökas efter varje iteration tills den når värden när rapporten är oberättigat. Detta kommer att ske senare i de viktigaste loopen genom att kontrollera statusReport flagga. Som regel aldrig aldrig utföra något så sakta skriva uppgifterna vidare till följetong från inom en avbrott rutin. Funktionen loop() tolkar och kör kommandon när emot, det rapporterar sedan status om flaggan tas upp av timer-avbrott. För att läsa en sträng från seriella bufferten, loop() förlitar sig på den serialEvent() funktion som kommer att definieras i slutet: denna rutin körs mellan varje gång loop() körs. Det är inte väldokumenterat och det förmodligen gäller inte för alla Arduino modeller; i vilket fall är det inte svårt att kapsla dess innehåll inom viktigaste kretsar (se slutet av thi steg). void loop() {int intValue = 0;
om (stringComplete) {Serial.println(inputString); boolean stringOK = false; om (inputString.startsWith ("CMD")) {inputString = inputString.substring(4); Vi kontrollera först om den mottagna strängen börjar med "CMD": om så vi kan ignorera de första fyra tecknen, annars vi ska senare höja ett fel.
int pos = inputString.indexOf('='); om (pos > -1) {kommandot = inputString.substring (0, pos), värde = inputString.substring (pos + 1, inputString.length()-1); / / extraheringskommandot upp till \n studerandena det finns två typer av kommandon: de anger ett värde, där hittar vi "=" separera variabel + värdeparet, och de där kommandot är ett enda direktiv (STATUS). Om "=" vid pos, är strängen uppdelade i kommandot (vänstra delen) och värde (högra delen), släppa både den "=" i mellan och end-of-line karaktär i slutet.
om (command.equals("RED")) {/ / röd = ON| AV value.equals("ON")? digitalWrite (led3Pin, hög): digitalWrite (led3Pin, låg); stringOK = sant; } else om (command.equals("GREEN")) {/ / grön = ON| AV value.equals("ON")? digitalWrite (led2Pin, hög): digitalWrite (led2Pin, låg); stringOK = sant; } else om (command.equals("YELLOW")) {/ / gul = ON| AV value.equals("ON")? digitalWrite (led1Pin, hög): digitalWrite (led1Pin, låg); stringOK = sant; } Vi undersöker och LED kommandon; Observera att koden endast kontrollerar att värdet på: om du skriver grön = ASD det kommer att tolkas som grön = OFF. Det är inte perfekt, men den håller saker mycket enklare. stringOK = true anges varje gång ett kommando är erkänt och utförs så att fel kommandon kommer att flaggas senare.
annars om (command.equals("TMAX")) {/ / TMAX = värde intValue = value.toInt(); om (intValue > 0) {maxTemp = (float) intValue; maxTempSensor = (int) ((maxTemp/100 + 5) * 204,8); stringOK = true;}} else om (command.equals("SECONDS")) {/ / sekunder = värde intValue = value.toInt(); om (intValue > 0) {maxSeconds = intValue; stringOK = true;}} När värdet bör vara ett nummer, måste vi konvertera samt test det är verkligen ett nummer. När det gäller MaxTemp beräkna vi också värdet sensor som förklaras i avsnittet variabel definition
} / / pos >-1 annat if (inputString.startsWith("STATUS")) {Serial.print ("STATUS röd ="); Serial.println(digitalRead(led3Pin)); Serial.Print ("STATUS grön ="); Serial.println(digitalRead(led2Pin)); Serial.Print ("STATUS gul ="); Serial.println(digitalRead(led1Pin)); Serial.Print ("STATUS TMAX ="); Serial.println(maxTemp); Serial.Print ("STATUS sekunder ="); Serial.println(maxSeconds); Serial.Print ("STATUS TEMP ="); Serial.println(temperature); Serial.Print ("STATUS lår ="); Serial.println(tempHigh); stringOK = sant; } / utgångar inputString.startsWith("STATUS") om kommandot STATUS, programmet helt enkelt all information till följetong.
} / / inputString.startsWith ("CMD") stringOK? Serial.println ("kommandot körs"): Serial.println ("Ogiltigt kommando"); Signal om ett giltigt eller ogiltigt kommando har mottagits.
Rensa strängen för nästa iteration inputString = ""; stringComplete = false; } / / stringComplete variabel städning för nästa kommando iteration.
om (statusReport) {temperatur = (tempVal * 0.0048828125 -.5) * 100. Serial.Print ("STATUS TEMP ="); Serial.println(temperature); Serial.Print ("STATUS lår ="); Serial.println(tempHigh); statusReport = false; {}} Om rutinen avbrott har höjt flaggan statusReport, viss information skrivs ut på följetong och flaggan är avmarkerad. Observera att nuvarande temperatur värdet beräknas på denna punkt: därför, om du utfärda en STATUS mellan statusReport intervallet, får du det gamla temperatur värdet. Som redan nämnts, serialEvent() inträffar när en nya data kommer i hårdvara seriell RX. Denna rutin är köra mellan varje gång loop() körs, så använder dröjsmål inuti loop kan fördröja svar. Finns kanske flera byte data. void serialEvent() {medan (Serial.available()) {/ / få den nya byten: char inChar = (char)Serial.read(); / / lägga till inputString: inputString += inChar; / / om det inkommande tecknet är en newline eller vagnretur, ange en flagga / / så huvudloop kan göra något åt det: om (inChar == '\n' || inChar == '\r') {stringComplete = sant;}}}