Stap 4: Arduino ontvangersmodule
Laten we overgaan tot het harde deel, de Arduino ontvangersmodule dat ik de "moeder" Arduino noemen. Eigenlijk is het niet zo moeilijk, maar je moet aandacht besteden.
Al eerder, zoals we zullen beginnen met bedrading van de Arduino. Nogmaals gebruikte ik pin 2 op de Arduino voor de ontvangergegevens pin en pin 3 voor de zendervan gegevens pin. Het Bluefruit -bord is verbonden als volgt (standaardconfiguratie):
- CTS op pin 11
- TXO op pin 10
- RXI op pin 9
- VIN op 5V
- GND op GND
De MOD, RTS en DFU pennen worden niet gebruikt in dit voorbeeld. Merk op dat voor dit voorbeeld de Bluefruit Raad van bestuur moet worden ingesteld op CMD modus op de kleine switch.
Ik heb verbonden 3 LEDs met een weerstand van 220 Ω voor elke één van hen te pinnen 5, 6 en 7. Dit is optioneel, maar kan nuttig zijn in sommige gevallen.
Nu dat de bedrading is gedaan, kunnen we beginnen met coderen. U moet verschillende bibliotheken te laten werken. De Arduino.h, SPI.h en SoftwareSerial.h bibliotheken zijn is reeds aanwezig in de Arduino IDE en RH_ASK.h degene die we in de vorige code gebruikt. De Adafruit_BLE.h, Adafruit_BluefruitLE_SPI.h en Adafruit_BluefruitLE_UART.h bibliotheken kunnen worden gedownload van Adafruit van website. BluefruitConfig.h is een configuratiebestand voor het Bluefruit board.
#include < Arduino.h >#include < RH_ASK.h >
#include <SPI.h >
#if niet gedefinieerd (_VARIANT_ARDUINO_DUE_X_) & & niet gedefinieerd (_VARIANT_ARDUINO_ZERO_)
#include <SoftwareSerial.h >
#endif
#include "Adafruit_BLE.h"
#include "Adafruit_BluefruitLE_SPI.h"
#include "Adafruit_BluefruitLE_UART.h"
#include "BluefruitConfig.h"
Hier zijn de globale variabelen gebruikt in deze code:
De variabelen van de nbRooms bepaalt het aantal kamers, zorg ervoor dat u deze kunt wijzigen als u meer of minder dan 3 zender Arduinos
De variabelen waarden is een matrix van lengte-nbRooms die worden gebruikt voor het opslaan van de gegevens van de zender Arduinos ontvangen.
De LEDpin -variabele is een array met daarin de pincodes voor de LEDs.
De limiet -variabele is een array die de limieten voor de helderheid waarmee de lichten worden beschouwd als slaat in- of uitschakelen. Merk op dat ik vergat om de 3 vervangen door de variabele nbRooms , die je moet doen.
De tijd en currentTime variabelen worden gebruikt voor het opslaan van waarden, verkregen uit de millis -functie.
De dataToSend -variabele wordt gebruikt voor het opslaan van de gegevens worden verzonden naar de Smartphone
De variabele aanvragen is een array van de char met de verzoeken om de zender Arduinos verzenden. Vergeet niet om dit te veranderen als u een verschillend aantal zenders gebruikt.
De * verzoek variabele is een verwijzing naar het verzoek om te worden verzonden naar de zender Arduino.
De booleans gotResponse, firstRequest en sturen zal later worden verklaard.
int waarden [nbRooms]; Gebruikt voor het opslaan van de gegevens verzameld uit de de zenders
int [LEDpin] = {5, 6, 7}; Pinnen gebruikt voor de LEDs
int limiet [3]; Gebruikt voor het opslaan van de grenzen van de helderheid waarop het licht wordt beschouwd als uitgeschakeld
Gebruikt voor het opslaan van de millis()-waarden
unsignedlong tijd;
unsignedlong currentTime;
String dataToSend; Gebruikt voor het opslaan van de gegevens die worden verzonden naar de Smartphone
char * verzoekt [] = {"a0", "a1", "a2"}; Gebruikt voor het opslaan van de verzoeken, vergeet niet om het te veranderen als u meer of minder dan 3 zender Arduinos
char * verzoeken; Gebruikt voor het opslaan van het verzoek om te worden verzonden
BOOL gotResponse = false;
BOOL firstRequest = true;
BOOL bleIsConnected = false;
BOOL verzenden = true; Voor het stoppen van de uitzending BLE
In dit deel maken we de noodzakelijke objecten.
Zoals voordat we het RH_ASK -object met de naam driver, maar dit keer maken u de Ptt -pin instellen op een ongebruikte (of pins -1) moet, omdat de standaardwaarde is één pin 10 die al wordt gebruikt door de Bluefruit-board.
Dan maken we de bluefruitSS en ble -objecten. De parameters die worden gebruikt voor deze objecten zijn die zijn opgegeven in het bestand BluefruitConfig.h .
Parameters voor de SoftwareSerial en de Adafruit_BluefruitLE_UART opgeslagen in BluefruitConfig bestand
SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN);
Adafruit_BluefruitLE_UART ble (bluefruitSS, BLUEFRUIT_UART_MODE_PIN, BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN);
Vervolgens zijn sommige definities van de instelling. De ene geeft aan als u wilt dat het bestuur van de Bluefruit voor het uitvoeren van een fabriek reset wanneer het begint. Het tweede argument definieert de minimale firmwareversie en de laatste die het gedrag van de rode LED op het bord. Ik beveel deze instellingen ongewijzigd te verlaten.
#define FACTORYRESET_ENABLE 1#define MINIMUM_FIRMWARE_VERSION "0.6.6"
#define MODE_LED_BEHAVIOUR "MODE"
Wij zullen in het setup -gedeelte beginnen door de pennen van de LED op de uitvoermodus . Wij stel alle de grenzen op 0 zodat ze niet null, die zou ons verhinderen een vergelijking te maken. Ze wordt later gewijzigd op de mobiele app.
voidsetup(void){
for (int i = 0; ik < sizeof(LEDpin); i ++)
{
pinMode (LEDpin [i], uitvoer); Initialisatie LED pinnen
}
for (int i = 0; ik < nbRooms; i ++)
{
limiet [i] = 0; Initialisatie van de grenzen op 0
}
Seriële.begin(9600); Voor foutopsporing
Als (! driver.init()) / / als de RF modules niet initialiseren
Seriële.println ("init mislukt");
Dit gedeelte van de installatie behandelt de configuratie van de Raad van bestuur Bluefruit. De setupBluefruit functie zal later worden verklaard. De code na het verandert de board LED modus (indien de firmwareversie ten minste 0.6.6 is) en stel het bord op de weergave van de gegevens, zodat het met de Smartphone communiceren kan.
setupBluefruit();Seriële.println(F("***"));
LED-activiteit opdracht wordt alleen ondersteund vanaf 0.6.6
Als (ble.isVersionAtLeast(MINIMUM_FIRMWARE_VERSION))
{
Modus LED activiteit wijzigen
Seriële.println (F ("Verandering LED-activiteit te" MODE_LED_BEHAVIOUR));
ble.sendCommandCheckOK ("AT + HWModeLED =" MODE_LED_BEHAVIOUR);
}
Set module Gegevensmodus
Seriële.println (F ("overschakelen naar Gegevensmodus!"));
ble.setMode(BLUEFRUIT_MODE_DATA);
Seriële.println(F("***"));
}
In het deel van de lus , zullen we omgaan met de ontvangst van de gegevens van de zender Arduinos, de overdracht van deze gegevens aan de Smartphone en de ontvangst van de grenzen van de Smartphone.
De gegevens verzamelen en doorgeven-deel is binnen een if expressie zodat u de uitzending BLE stoppen kunt als u wilt, die ik niet heb gedaan.
Wij zullen vervolgens doorlopen elke kamer, de gotResponse ingesteld op false en verzend een verzoek. Tegelijkertijd starten we een timer door een waarde toe te wijzen aan de variabele van de tijd met de millis -functie.
{
Als (verzenden) / / voor het stoppen van de uitzending BLE
{
for (int i = 0; ik < nbRooms; i ++)
{
gotResponse = false;
Aanvraag versturen
tijd = millis(); Start timer
sendRequest(i); Verzoek verzenden zender Arduino
Terwijl wij geen antwoord van de zender Arduino hebt ontvangen, slaan we de millis-waarde in de variabele currentTime om het te vergelijken met de tijd. Als het verschil groter is dan 500 milliseconden, betekent dit dat de boodschap verloren was, en dat we moeten een andere aanvraag te versturen. We moeten ook opnieuw de variabele van de tijd .
Reactie ontvangenterwijl (! gotResponse) / / terwijl geen reactie heeft ontvangen zijn
{
currentTime = millis();
Als (currentTime - tijd > 500) / / als 0,5 seconden is verstreken zonder een antwoord te ontvangen, verzenden verzoek
{
tijd = millis(); Opnieuw instellen van de timer
Seriële.println ("geen reactie na 0,5 seconde, aanvraag opnieuw te zenden");
sendRequest(i);
}
Opnieuw creëren we een buffer om op te slaan van de ontvangen gegevens. Na ontvangst, wij het bericht opslaan in een string-variabele en parseren van de kamer en gegevenswaarden. Als de kamer komt overeen met de verwachte een, we dan gotResponse ingesteld op true en de gegevens worden opgeslagen in de matrix values .
uint8_t buf [4]; Buffer die wordt gebruikt voor het opslaan van de ontvangen gegevens, de grootte is ingesteld op 3 bytes, omdat de gegevens: String(room) + waarde (bijv. 0555)uint8_t buflen = sizeof(buf);
Als (driver.recv (buf, & buflen)) / / na ontvangst van de gegevens
{
Koord bericht = (char *) buf; Opslaan van gegevens in een tekenreeks om te worden geparseerd
int kamer = message.substring (0, 1).toInt(); Parsing kamernummer
int gegevens = message.substring(1).toInt(); Parseren van gegevens
Als (kamer == ik) / / als de gegevens uit de juiste kamer
{
gotResponse = true;
waarden [ruimte] = gegevens; Opslaan van de gegevens
In dit deel behandelen we de bliksem van de LED's. Dit is optioneel.
Draaien van de LEDs in- en uitschakelenAls (waarden [ruimte] > limit[room])
{
digitalWrite (LEDpin [i], hoge);
}
anders
{
digitalWrite (LEDpin [i], laag);
}
Voor foutopsporing
Seriële.print ("Data voor kamer");
Seriële.print(room);
Seriële.print ("is");
Seriële.println(data);
Seriële.println("");
}
}
}
delay(50);
}
Zodra we hebben ontvangen en gecontroleerd de gegevens vanuit elke kamer, kunnen we gaan tot de overdracht van deze gegevens aan de Smartphone. Het bericht begint met een "#" en eindigt met een "*" om het gemakkelijk te ontleden in de Smartphone-app. We scheiden ook de waarden met een "/".
dataToSend = "#"; Gegevensreeks beginnen met # voor easyier ontleden door de Smartphone-appfor (int i = 0; ik < nbRooms; i ++)
{
dataToSend.concat(String(values[i]));
Als (ik < nbRooms - 1)
{
dataToSend.concat("/"); Scheid de waarden met een /
}
}
dataToSend.concat("*"); Einde van de tekenreeks van de data met *
Seriële.print ("verzenden:");
Seriële.println(dataToSend);
Seriële.println("");
}
Het bericht wordt vervolgens opgeslagen in een matrix van de char en verzonden naar de Smartphone whit de ble.print -methode.
n, char ingangen [BUFSIZE + 1]; Gebruikt voor het opslaan van de gegevens worden verzonden naar SmartphonedataToSend.toCharArray (ingangen, BUFSIZE + 1); Gegevensreeks aan buffer kopiëren
ble.Print(inputs); Gegevens verzenden
Daarna komt de receptie van de grenzen die zijn verzonden door de Smartphone. We beginnen met het maken van een stringvariabele naam waarden (niet hetzelfde als de int-array!) waarin de tekens dat is ontvangen via de BLE-connectie worden opgeslagen. Zodra we hebben gelezen de #, d.w.z. het uitgangspunt van het bericht, we stelt u de variabele opnemen op true waardoor de aaneenschakeling van de volgende tekens aan de variabele waarden , tot de * wordt gelezen. Wanneer het bericht klaar is, wij ontleden en bewaren van de grenzen met de setLimits functie die zal later worden verklaard.
Tekenreekswaarden = ""; Legen van de gegevensreeksLezing van Smartphone ontvangen gegevens
BOOL opname = false;
terwijl (ble.available()) / / Hoewel er gegevens beschikbaar uit BLE
{
int c = ble.read();
Seriële.println((char)c);
Als (opname) / / als we de # heb gelezen
{
Als (c (char)! = ' *')
{
values.concat((char)c); Zolang c van het einde-teken verschilt *, toe te voegen aan de tekenreeks van de data
}
anders
{
Seriële.println(values); setLimits(values);
opname = false; De grenzen stellen aan degene die we zopas
waarden = "";
}
}
Als ((char) c == '#') / / beginnen met opnemen na ontvangst van het begin #-teken
{
opname = true;
}
}
}
Hier zijn de functies die worden gebruikt in de code.
De eerste wordt een foutbericht weergegeven en stopt de uitvoering van het programma.
VOID fout (const __FlashStringHelper * err)
{
Seriële.println(err);
terwijl (1);
}
Deze functie configureert het bord Bluefruit wanneer het wordt gestart. Het voert ook een fabriek reset als het is ingeschakeld.
VOID setupBluefruit(){
/ * De module initialiseren * /
Seriële.print (F ("initialiseren van de Bluefruit-LE-module:"));
Als (! ble.begin(VERBOSE_MODE))
{
fout (F ("kon niet vinden Bluefruit, zorg ervoor dat het in de Command stand & Controleer bedrading?"));
}
Seriële.println (F("OK!"));
Als (FACTORYRESET_ENABLE)
{
/ * Uitvoeren van een fabriek reset om ervoor te zorgen dat alles is in een bekende status * /
Seriële.println (F ("het uitvoeren van een fabriek reset:"));
Als (! ble.factoryReset()) {}
fout (F ("niet kon fabrieksinstellingen"));
}
}
/ * Uitschakelen commando echo van Bluefruit * /
ble.echo(false);
Seriële.println ("aanvragen Bluefruit info:");
/ * Bluefruit informatie afdrukken * /
ble.info();
ble.verbose(false);
}
Deze functies wordt gebruikt voor het verzenden van verzoeken naar de zender Arduinos, met het identificatienummer van de kamer als parameter.
Een verzoek verzonden naar de overeenkomstige Ruimtezender (i)VOID sendRequest(int i)
{
verzoek = verzoeken [i];
driver.send ((uint8_t *) verzoek, strlen(request));
driver.waitPacketSent();
Seriële.print ("verzoek dat naar de kamer verzonden");
Seriële.println(i);
Seriële.println ("wacht op antwoord");
Seriële.println("");
}
Deze functies parseert het limiet bericht ontvangen van de Smartphone en de grenzen wordt opgeslagen in de matrix van de limiet .
Opslaan van de grenzenVOID setLimits(String values)
{
for (int i = 0; ik < nbRooms; i ++)
{
Als (ik < nbRooms - 1)
{
limiet [i] = values.substring (4 * i, 3 + 4 * i).toInt(); Pärsing de grenzen
}
anders
{
limiet [i] = values.substring (4 * i).toInt(); Parseren van de laatste grens
}
}
}