Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Manufacturing Technology >> Productieproces

Een betrouwbare Arduino-gebaseerde draadloze weerstation bouwen

In deze tutorial leer je hoe je een Arduino-gebaseerd draadloos weerstation maakt. Je kunt de volgende video bekijken of de geschreven tutorial hieronder lezen.

Overzicht

De buitentemperatuur en -vochtigheid worden gemeten met de DHT22-sensor en deze data wordt draadloos verstuurd naar de binnenunit met behulp van NRF24L01-transceivermodules. Aan de binnenunit zit ook een DHT22-sensor voor het meten van de binnentemperatuur en -vochtigheid, evenals een DS3231 Real Time Clock-module die de tijd bijhoudt zelfs als de Arduino stroom verliest. Al deze data wordt weergegeven op een 0,96" OLED-display.

Een betrouwbare Arduino-gebaseerde draadloze weerstation bouwen

Arduino draadloos weerstation schakelschema

Laten we kijken naar het schakelschema en hoe dit project werkt. Let op dat ik al gedetailleerde tutorials heb over hoe elk van deze modules werkt, dus voor meer details kun je ze bekijken: NRF24L01 Tutorial, DHT22 Tutorial, DS3231 Tutorial.

Een betrouwbare Arduino-gebaseerde draadloze weerstation bouwen

Je kunt de benodigde componenten voor dit project via de onderstaande links verkrijgen:

  • NRF24L01 Transceiver Module
  • DHT22 Sensor
  • DS3231 Real Time Clock
  • Arduino Nano

Zowel de real-time clock-module als het OLED-display gebruiken het I2C-protocol voor communicatie met de Arduino, dus ze zijn aangesloten op de I2C-pennen of analoge pennen 4 en 5 op de Arduino Nano. Recht naast de NRF24L01-transceiver zit een condensator om de voeding stabieler te maken. Er zit ook een pull-up-weerstand op de datapin van de DHT22 zodat de sensor correct werkt.

Wat de voeding betreft: ik gebruikte een 12V DC-adapter voor de binnenunit, en voor de buiteneenheid twee Li-ion-batterijen die samen ongeveer 7,5V leveren. Met deze configuratie kan de buiteneenheid ongeveer 10 dagen draaien voordat de batterijen leeg zijn, omdat we periodiek data versturen en de Arduino in de tussentijd in slaapmodus zetten, waarbij de stroomverbruik slechts ongeveer 7mA bedraagt.

Custom design PCB

Om de elektronische componenten georganiseerd te houden, heb ik volgens het schakelschema een custom PCB ontworpen met de gratis online ontwerpsoftware EasyEDA. We kunnen zien dat dezelfde PCB voor zowel de binnen- als buiteneenheid kan worden gebruikt, alleen de Arduino moet anders geprogrammeerd worden.

Een betrouwbare Arduino-gebaseerde draadloze weerstation bouwen

Zodra het ontwerp klaar is, exporteren we het Gerber-bestand dat gebruikt wordt voor de PCB-fabricage. Je kunt de EasyEDA-projectbestanden van het Arduino draadloze weerstation hier bekijken.

Vervolgens bestellen we de PCB bij JLCPCB, de sponsor van deze video.

Een betrouwbare Arduino-gebaseerde draadloze weerstation bouwen

We slepen het Gerber-bestand in de uploader, controleren de PCB in de Gerber-viewer, selecteer de gewenste eigenschappen en bestellen tegen een redelijke prijs. Let op: bij je eerste bestelling bij JLCPCB kun je tot 10 PCBs voor slechts $2 krijgen.

Een betrouwbare Arduino-gebaseerde draadloze weerstation bouwen

Na enkele dagen zijn de PCBs aangeleverd. De kwaliteit is geweldig en alles klopt precies met het ontwerp.

Een betrouwbare Arduino-gebaseerde draadloze weerstation bouwen

Ik begon met het assembleren door pinheaders op de PCB te solderen, zodat we componenten gemakkelijk kunnen aansluiten en loskoppelen.

Een betrouwbare Arduino-gebaseerde draadloze weerstation bouwen

Daarna soldeerde ik de condensator en de pull-up-weerstand. Met deze stap klaar, kunnen we de componenten op de pinheaders van de PCB plaatsen.

Een betrouwbare Arduino-gebaseerde draadloze weerstation bouwen

Vervolgens maakte ik de behuizingen. Ik gebruikte 8mm dik MDF-bord en zaagde alle stukken op maat met een cirkelzaag.

Een betrouwbare Arduino-gebaseerde draadloze weerstation bouwen

Voor nauwkeurige metingen moeten de zijkanten van de behuizingen lucht doorlaten. Ik boorde en raspt meerdere sleuven in de zijpaneelen van zowel de binnen- als buiteneenheid.

Een betrouwbare Arduino-gebaseerde draadloze weerstation bouwen

Ik maakte ook een sleuf voor het OLED-display op het frontpaneel en zaagde een klein aluminiumstukje op maat voor decoratie.

Een betrouwbare Arduino-gebaseerde draadloze weerstation bouwen
Een betrouwbare Arduino-gebaseerde draadloze weerstation bouwen

Voor het samenstellen gebruikte ik houtlijm, klemmen en schroeven. Ik schilderde de behuizingen met spuitbusverf: wit voor de buiteneenheid, zwart voor de binnenunit. Na het drogen plaatste ik de PCBs in de behuizingen.

Een betrouwbare Arduino-gebaseerde draadloze weerstation bouwen
Een betrouwbare Arduino-gebaseerde draadloze weerstation bouwen

Aan de achterkant van de binnenunit monteurde ik een voedingsjack en een aan/uitschakelaar, en aan de buiteneenheid gebruikte ik een simpele jumper-draad als schakelaar. En klaar is ons Arduino draadloze weerstation, maar we moeten nog kijken hoe de code werkt.

Arduino draadloos weerstation code

Buiteneenheid (Zender) code

/* Arduino Draadloze Communicatie Tutorial Buiteneenheid - Zender by Dejan Nedelkovski, www.HowToMechatronics.com Bibliotheken: NRF24L01 - TMRh20/RF24, https://github.com/tmrh20/RF24/ DHT22 - DHTlib, https://github.com/RobTillaart/Arduino/tree/master/libraries/DHTlib LowPower - https://github.com/rocketscream/Low-Power */
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <dht.h>
#include <LowPower.h>

#define dataPin 8 // DHT22 datapin
dht DHT; // Maak DHT-object aan
RF24 radio(10, 9); // CE, CSN
const byte address[6] = "00001";
char thChar[32] = "";
String thString = "";

void setup() {
  radio.begin();
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_MIN);
  radio.stopListening();
}

void loop() {
  int readData = DHT.read22(dataPin); // Lees data van sensor
  int t = DHT.temperature; // Temperatuur
  int h = DHT.humidity; // Vochtigheid
  thString = String(t) + String(h);
  thString.toCharArray(thChar, 12);
  // Verstuur data draadloos naar binnenunit
  for (int i = 0; i <= 3; i++) { // Verstuur 3 keer voor zekerheid
    radio.write(&thChar, sizeof(thChar));
    delay(50);
  }
  // Slaap 2 minuten (15 * 8s = 120s)
  for (int sleepCounter = 15; sleepCounter > 0; sleepCounter--) {
    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
  }
}

Beschrijving: De buiteneenheid is de zender. We includeren de RF24-, DHT- en LowPower-bibliotheek (voor slaapmodus). Na het definiëren van instanties, pinnen en variabelen, initialiseren we in setup het draadloze communicatie-adres. In de loop lezen we temperatuur en vochtigheid van de DHT22. Deze gehele getallen converteren we naar één String, plaatsen ze in een character-array en versturen ze met radio.write(). We sturen 3 keer om te zorgen dat de ontvanger de data ontvangt, zelfs als hij bezig is. Ten slotte zetten we de Arduino 2 minuten in slaapmodus om stroom te besparen.

Binnenunit (Ontvanger) code

/* Arduino Draadloze Communicatie Tutorial Binnenunit - Ontvanger by Dejan Nedelkovski, www.HowToMechatronics.com Bibliotheken: DS3231 - https://www.rinkydinkelectronics.com/library.php?id=73 U8G2 - https://github.com/olikraus/u8g2 */
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <dht.h>
#include <DS3231.h>
#include <U8g2lib.h>
#include <Wire.h>

#define dataPin 8 // DHT22 sensor
dht DHT;
DS3231 rtc(SDA, SCL);
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
RF24 radio(10, 9);
const byte address[6] = "00001";
char text[6] = "";
int readDHT22, t, h;
String inTemp, inHum, outTemp, outHum;
String rtcTime, rtcDate;
int draw_state = 0;
unsigned long previousMillis = 0;
long interval = 3000;

#define Temperature_20Icon_width 27
#define Temperature_20Icon_height 47
static const unsigned char Temperature_20Icon_bits[] U8X8_PROGMEM = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x80, 0x7f, 0x00, 0x00, 0xc0, 0xe1, 0x00, 0x00,
  0xe0, 0xc0, 0x01, 0x00, 0x60, 0x80, 0xf9, 0x03, 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x01, 0x00,
  0x60, 0x80, 0x79, 0x00, 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0xf9, 0x03,
  0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x01, 0x00, 0x60, 0x8c, 0x79, 0x00, 0x60, 0x9e, 0x01, 0x00,
  0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0xf9, 0x03, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00,
  0x60, 0x9e, 0x79, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0xf9, 0x03,
  0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x70, 0x9e, 0x03, 0x00,
  0x38, 0x1e, 0x07, 0x00, 0x18, 0x3e, 0x0e, 0x00, 0x1c, 0x3f, 0x0c, 0x00, 0x0c, 0x7f, 0x18, 0x00,
  0x8c, 0xff, 0x18, 0x00, 0x8e, 0xff, 0x38, 0x00, 0xc6, 0xff, 0x31, 0x00, 0xc6, 0xff, 0x31, 0x00,
  0xc6, 0xff, 0x31, 0x00, 0x8e, 0xff, 0x38, 0x00, 0x8c, 0xff, 0x18, 0x00, 0x0c, 0x7f, 0x1c, 0x00,
  0x3c, 0x1c, 0x0e, 0x00, 0x78, 0x00, 0x06, 0x00, 0xe0, 0x80, 0x07, 0x00, 0xe0, 0xff, 0x03, 0x00,
  0x80, 0xff, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

#define Humidity_20Icon_width 27
#define Humidity_20Icon_height 47
static const unsigned char Humidity_20Icon_bits[] U8X8_PROGMEM = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
  0x00, 0xf8, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, 0xdc, 0x01, 0x00, 0x00, 0x8e, 0x01, 0x00,
  0x00, 0x86, 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x03, 0x07, 0x00, 0x80, 0x03, 0x06, 0x00,
  0x80, 0x01, 0x0c, 0x00, 0xc0, 0x01, 0x1c, 0x00, 0xc0, 0x00, 0x18, 0x00, 0xe0, 0x00, 0x38, 0x00,
  0x60, 0x00, 0x30, 0x00, 0x70, 0x00, 0x70, 0x00, 0x30, 0x00, 0xe0, 0x00, 0x38, 0x00, 0xc0, 0x00,
  0x18, 0x00, 0xc0, 0x01, 0x1c, 0x00, 0x80, 0x01, 0x0c, 0x00, 0x80, 0x03, 0x0e, 0x00, 0x80, 0x03,
  0x06, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x07, 0x03, 0x00, 0x00, 0x06,
  0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x63, 0x00, 0x00, 0x06,
  0x63, 0x00, 0x00, 0x06, 0x63, 0x00, 0x00, 0x06, 0xe3, 0x00, 0x00, 0x06, 0xc7, 0x00, 0x00, 0x06,
  0xc6, 0x01, 0x00, 0x07, 0x86, 0x03, 0x00, 0x03, 0x0e, 0x1f, 0x00, 0x03, 0x0e, 0x1e, 0x80, 0x01,
  0x1c, 0x00, 0xc0, 0x01, 0x38, 0x00, 0xe0, 0x00, 0x78, 0x00, 0x70, 0x00, 0xf0, 0x00, 0x38, 0x00,
  0xe0, 0x07, 0x1f, 0x00, 0x80, 0xff, 0x0f, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00
};

void setup() {
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_MIN);
  radio.startListening();
  u8g2.begin();
  rtc.begin();
}

void loop() {
  if (radio.available()) {
    radio.read(&text, sizeof(text));
    outTemp = String(text[0]) + String(text[1]) + char(176) + "C";
    outHum = String(text[2]) + String(text[3]) + "%";
  }
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;
    u8g2.firstPage();
    do {
      switch (draw_state) {
        case 0: drawDate(); break;
        case 1: drawInTemperature(); break;
        case 2: drawInHumidity(); break;
        case 3: drawOutTemperature(); break;
        case 4: drawOutHumidity(); break;
      }
    } while (u8g2.nextPage());
    draw_state++;
    if (draw_state > 4) draw_state = 0;
  }
}

void drawDate() {
  String dowa = rtc.getDOWStr();
  dowa.remove(3);
  rtcDate = dowa + " " + rtc.getDateStr();
  u8g2.setFont(u8g2_font_timB14_tr);
  u8g2.setCursor(0, 15);
  rtcTime = rtc.getTimeStr();
  rtcTime.remove(5);
  u8g2.print(rtcDate);
  u8g2.setFont(u8g2_font_fub30_tf);
  u8g2.setCursor(8, 58);
  u8g2.print(rtcTime);
}

void drawInTemperature() {
  readDHT22 = DHT.read22(dataPin);
  t = DHT.temperature;
  inTemp = String(t) + char(176) + "C";
  u8g2.setFont(u8g2_font_helvR14_tr);
  u8g2.setCursor(24, 15);
  u8g2.print("INDOOR");
  u8g2.setFont(u8g2_font_fub30_tf);
  u8g2.setCursor(36, 58);
  u8g2.print(inTemp);
  u8g2.drawXBMP(0, 17, Temperature_20Icon_width, Temperature_20Icon_height, Temperature_20Icon_bits);
}

void drawInHumidity() {
  h = DHT.humidity;
  inHum = String(h) + "%";
  u8g2.setFont(u8g2_font_helvR14_tr);
  u8g2.setCursor(24, 15);
  u8g2.print("INDOOR");
  u8g2.setFont(u8g2_font_fub30_tf);
  u8g2.setCursor(36, 58);
  u8g2.print(inHum);
  u8g2.drawXBMP(0, 17, Humidity_20Icon_width, Humidity_20Icon_height, Humidity_20Icon_bits);
}

void drawOutTemperature() {
  u8g2.setFont(u8g2_font_helvR14_tr);
  u8g2.setCursor(12, 15);
  u8g2.print("OUTDOOR");
  u8g2.setFont(u8g2_font_fub30_tf);
  u8g2.setCursor(36, 58);
  u8g2.print(outTemp);
  u8g2.drawXBMP(0, 17, Temperature_20Icon_width, Temperature_20Icon_height, Temperature_20Icon_bits);
}

void drawOutHumidity() {
  u8g2.setFont(u8g2_font_helvR14_tr);
  u8g2.setCursor(12, 15);
  u8g2.print("OUTDOOR");
  u8g2.setFont(u8g2_font_fub30_tf);
  u8g2.setCursor(36, 58);
  u8g2.print(outHum);
  u8g2.drawXBMP(0, 17, Humidity_20Icon_width, Humidity_20Icon_height, Humidity_20Icon_bits);
}

Beschrijving: Aan de ontvangerkant (binnenunit) includeren we twee extra bibliotheken: één voor de DS3231 real-time clock en één voor het OLED-display (U8G2-bibliotheek). Op dezelfde manier definiëren we instanties, pinnen en variabelen. Ook definiëren we de temperatuur- en vochtigheidspictogrammen als bitmaps.

Voor het maken van bitmaps kun je GIMP gebruiken (gratis afbeeldingseditor), waarin je alles kunt tekenen en exporteren als bitmap (.xbm). Open dit bestand in Kladblok en kopieer de bitmapdata in de Arduino-code. Let op dat we de bitmap als constant definiëren met PROGMEM, zodat deze in de flash-geheugen wordt opgeslagen in plaats van SRAM.

static const unsigned char Temperature_20Icon_bits[] U8X8_PROGMEM // Opslaan in Flash-geheugen
static unsigned char Temperature_20Icon_bits[] // Opslaan in SRAM

In setup initialiseren we de draadloze communicatie, het OLED-display en de real-time clock.

In de loop controleren we constant of er binnenkomende data beschikbaar is via de NRF24L01-modules. Zo ja, lezen we deze met radio.read() en slaan de eerste twee karakters op in de temperatuur-String, de volgende twee in de vochtigheid-String.

We gebruiken millis() om de verschillende data op het display weer te geven op intervallen (3 seconden). We gebruiken millis() in plaats van delay() zodat de rest van de code herhaald kan worden uitgevoerd; met delay() zou het programma wachten en we zouden binnenkomende data van de buiteneenheid kunnen missen.

Met de firstPage() en nextPage()-functies van de U8G2-bibliotheek printen we de vijf verschillende schermen die gedefinieerd zijn in custom functies.

De drawDate()-functie haalt datum en tijd op van de RTC-module en print het op het display. De drawInTemperature()-functie leest de binnentemperatuur en print deze. Dezelfde methode wordt gebruikt voor alle schermen.

Dat was het voor deze tutorial. Ik hoop dat je ervan hebt genoten en iets nieuws hebt geleerd. Stel gerust vragen in de reacties hieronder.

Productieproces

  1. DIY Zonne-energie Weerstation Met Raspberry Pi
  2. Een buitenweerstation bouwen met Raspberry Pi 2 en ADS-WS1
  3. Een Raspberry Pi-weerstation bouwen dat dagelijkse weergegevens e-mailt
  4. Geavanceerd Weerstation v2.0: Real-time Temperatuur, Druk, Vochtigheid & Hoogte Monitoring
  5. Arduino Audio Frequentie Detector – Meet de luidste geluidspieken met hoge gevoeligheid
  6. Slimme Draadloze Lichtschakelaar Controller: Arduino-gebaseerde Remote Switch Manipulator
  7. Arduino Boter-Kaas-Eieren met MAX7219 LED Matrix en Kartonnen Behuizing
  8. Bouw een Betrouwbare Arduino Afteltimer met SparkFun 7‑Segment Display
  9. Bouw een $10 Draagbare Arduino Weerstation (AWS) – Eenvoudige DIY met Nano, DHT22, BMP180 & LCD
  10. eDOT: Precieze Arduino-klok & weerstation met ingebouwde IR-remote
  11. Realtime Weerstation met Arduino & ThingSpeak IoT