Thermometer & Hygrometer auf ATMEGA 328P-MU - Erhöhung des Arduino-Entwicklungsniveaus

Heute möchte ich eines meiner Arduino-Projekte teilen. Es war einmal vor nicht allzu langer Zeit, irgendwo im Internet, als ich von Arduino erfuhr. Ich bin ziemlich schnell in dieses Geschäft eingetreten, der Einstieg ist dort nicht hoch. Nach einiger Zeit, nachdem ich bereits eine Reihe von Sensoren gesammelt hatte, kamen mir Sensoren für ein Smart Home in den Sinn, als ich dachte, dass alles irgendwie verrückt war. Module, große einfache Kisten, ein paar Drähte und Heißkleber :). Als ich meine Box mit einem Temperatursensor und zum Beispiel den Temperatursensor desselben Xiaomi betrachtete, wurde mir klar, dass ich möchte, dass sie wie Xiaomi aussieht, aber gleichzeitig könnte man sie wie meine in einer 10 x 6 cm großen Box mit Drähten und Schmelzkleber neu programmieren. Und wahrscheinlich wurde dann der Beginn meiner DIY-Arduino-Projekte auf Leiterplatten gelegt.

Im heutigen Artikel werden wir über einen Temperatur- und Feuchtigkeitssensor sprechen, der auf dem atmega328p-mu-Prozessor basiert. Dies ist eine "kleinere" Version (ein absolutes Analogon) des atmega328p-au-Prozessors (Arduino Uno, Pro Mini, Nano), die allen Arduino-Entwicklern bekannt ist. Wenn jemand meine Artikel schon einmal gelesen hat, weiß er, dass ich Mysensoren bevorzuge. Was ist das? Dies ist eine sehr einfache und gut gestaltete und, was wichtig ist, gut beschriebene Bibliothek für Arduino IDE (und nicht nur) zum Erstellen von IOT-Funknetzwerken mit Frequenzen von 2,4 GHz, 915, 868, 433 MHz sowie kabelgebundenen Netzwerken auf der 485-Schnittstelle, möglicherweise nicht alle erwähnt Das Protokoll wird ständig weiterentwickelt, es wird ständig etwas hinzugefügt.

Das erste, was getan wurde, war der Sensor selbst auf der Leiterplatte. Ich habe es getan, ohne den Fall zu betrachten. Nach dem Prinzip besteht die Hauptsache darin, einen Sensor herzustellen, und ich werde den Fall irgendwie drucken ... ja, tu das nicht :). Tatsächlich ist der Sensor selbst derselbe Arduinka Pro Mini, das Funkmodul nRF24l01, der Temperatur- und Feuchtigkeitssensor SHT20, nur ohne Kabel und Heißkleber. Von den "Schnickschnack" ist dies ein externes SPI-Flash-Laufwerk zum Blinken durch die Luft (der DualOptibut-Bootloader ist für den Betrieb erforderlich, später habe ich aufgehört, sie (Flash-Laufwerke) auf die Baugruppen zu setzen, da keine Firmware über die Luft und die Hälfte des Akkus vorhanden ist) und das "Kryptomikrofon" ATSHA204A sozusagen vollständig Hardware-Kit (in Mysensors müssen Sie zum Aktivieren von Signaturen, Verschlüsselung usw. nur das erforderliche #def am Anfang der Skizze angeben).



Das Board selbst wurde im Diptrace-Programm erstellt, nachdem man sich die Video-Tutorials auf YouTube angesehen hatte. Zuerst schien es etwas "Höllenhaftes" zu sein, aber in Wirklichkeit stellte sich heraus, dass es nicht so schwierig war. Ich habe Boards in China auf jlcpcb.com bestellt, 2 Dollar, jede Farbe, und nach 2 Wochen hast du bereits 10 Stücke "deiner eigenen Kreation" zur Hand :).





Der nächste Schritt war die Entwicklung des Körpers. Oh, das stellte sich als das gleiche Problem heraus. Im Allgemeinen suchte ich nicht nach einfachen Wegen, sondern beschloss, die Solid Works zu beherrschen. Wie sich herausstellte, ist dies überhaupt nicht wie bei Deeptrace. Trotzdem empfehle ich diesen Editor zum Studium. Der Lernprozess dauerte einen Monat, in dem Sie gemächlich Videolektionen auf YouTube ansehen und die Lektion im Editor wiederholen mussten. Bei der Entwicklung des Gehäuses wurde deutlich, dass die Herstellung einer Geräteplatine ohne Berücksichtigung der Parameter des zukünftigen Gehäuses eine schlechte Entscheidung ist. Aus der Serie, in der wir die Sticks in unsere eigenen Räder einsetzen, wird eine schlechte Entscheidung getroffen. Nach den Ergebnissen der Board-Versionen kamen drei heraus, wobei die Installation des Boards in dem Fall berücksichtigt wurde, und ich denke, dies ist nicht die letzte Option.

Zu Beginn der Entwicklung des Gebäudes bestand die Idee darin, es auf einem FDM-3D-Drucker zu drucken. Je weiter im Wald, desto deutlicher wurde jedoch, dass nicht alle meine Wunschliste reproduziert werden konnten. Als dieses Verständnis kam, lernte ich bereits eine andere 3D-Drucktechnologie kennen - SLA. Ohne nachzudenken und von der Druckqualität beeindruckt zu sein, wurde die Wunschliste für Ali - ANYCUBIC Photon herausgegeben. (Link ana Ali, keine Werbung, kein Partner, ... nur ein Link).

Ich werde jetzt sofort schreiben, basierend auf meinen Erfahrungen zum Zeitpunkt dieses Schreibens, ... oh, diese coole Sache ist eine coole Sache !!! Der Fall, der natürlich im Editor entworfen und nicht zum ersten Mal gedruckt wurde, gab es viele Verbesserungen. Nun, es ist wahrscheinlich nicht umgekehrt. Als Ergebnis bekam ich das Ergebnis, das ich wollte. Ein Miniaturgerät, ein guter DIY-Koffer mit sehr präzisen Details, Knöpfen, Schriftarten und allem, was im Kopf dargestellt ist. Der hinteren Abdeckung wurde ein Magnet hinzugefügt, der nun problemlos auf Eisenoberflächen montiert werden kann.

















Dies sind Versuche, dasselbe Modell auf einem FDM-Drucker zu drucken:





Da sich herausstellte, dass das Gerät klein ist, es aber immer noch ein Arduinka ist, war ich verwirrt über die Ausgabe von Miniaturanschlüssen für die Programmierung. Dementsprechend wurde ein kleiner Adapter für die Anschlüsse für die bequeme Verbindung mit dem Programmierer und dem TTL-Konverter hergestellt.



Alles wurde auf Ali gekauft (ja, es gibt nicht nur vollständige Arduino-Module)

SMD-Tantalkondensator 4,7 uF - 4,7 uF | 10v | 10% - C1
SMD Keramikkondensator 100nF | Y5V - 100nF | 50v | + 80-20% - C2, C3, C4, C5, C6, C7
LED - LED SEITE - D1
Pin Header Buchse - 2x3P | 6pin | 1,27 mm - J1, J2
SMD-Widerstand 20K Ohm - 20K | 5% - R1
SMD-Widerstand 4,7 K Ohm - 4,7 K | 5% - R2, R3, R4
SMD-Widerstand 470K Ohm - 470 | 1% - R5
SMD-Widerstand 1M Ohm - 1M | 1% - R6
SMD-Widerstand 18K Ohm - 18K | 5% - R7
SMD-Widerstand 10K Ohm - 10K | 5% - R8
4-poliger SMD-Seitentaster - SW1, SW2
Serieller 512-Kbit-SPI-Flash-Speicher mit 1,65 V - AT25DF512C-SSHN-B - U1
Mini NRF24L01 + 2,4 GHz 1,27 MM RF - nRF24l01 1,27 SMD - U2
ATMEGA328P-MU QFN32 - U3
CRYPTO-AUTHENTIFIZIERUNG, 1 DRAHT - ATSHA204A-STUCZ-T - U4
Feuchtigkeits- und Temperatursensor IC - SHT20 - U5
BATTERIEHALTER FÜR CR2477-1 - L-KLS5-CR2477-1 - U6

Der Programmcode ist recht einfach. Ein Beispiel für die DFRobot-Bibliothek wurde für die Arbeit mit dem SHT20-Sensor verwendet. Grundsätzlich kann jede Skizze für jeden Sensor in 5 Minuten in eine Skizze für die Arbeit im Mysensors-Netzwerk umgewandelt werden.

Codeliste
#include <Wire.h>
#include "DFRobot_SHT20.h"
DFRobot_SHT20    sht20; // https://github.com/DFRobot/DFRobot_SHT20

#define MY_DEBUG
//#define MY_DISABLED_SERIAL
#define MY_RADIO_RF24
#define MY_PASSIVE_NODE
#define MY_NODE_ID 200
#define MY_PARENT_NODE_ID 0
#define MY_PARENT_NODE_IS_STATIC
#define MY_TRANSPORT_UPLINK_CHECK_DISABLED
//#define MY_OTA_FIRMWARE_FEATURE
//#define MY_SIGNING_ATSHA204
//#define MY_SIGNING_ATSHA204_PIN A3
//#define MY_SIGNING_REQUEST_SIGNATURES

#define TEMP_SENS_ID 1
#define HUM_SENS_ID 2
#define SETTING_LED_SENS_ID 100
#define DELAY_TIME_SENS_ID 101
#define BATTARY_SEND_SENS_ID 102
#define BATTARY_DATA_SENS_ID 103

#define BAT_COOF 3.04
#define BAT_MIN 195
#define BAT_MAX 295
#define ON 1
#define OFF 0

float humd;
float temp;
float oldhumd;
float oldtemp;
float tempThreshold = 0.5;
float humThreshold = 10.0;
static uint32_t lightMillis;
static uint32_t previousMillis;
uint32_t send_batteryTime;
uint32_t w_battetyTime = 0;
static uint8_t led_pin = 4;
static uint8_t mode_pin = 2; // interrupt
uint32_t delayTime;
int8_t battery;
int8_t old_battery;
uint8_t set_led;
boolean sleep_mode;
boolean configMode = 0;
int8_t timer_status = 0;
bool flag_mode_button = 0;
bool sleep_flag = 0;
bool listen_flag = 0;

#include <MySensors.h>

MyMessage msg_temp(TEMP_SENS_ID, V_TEMP);
MyMessage msg_hum(HUM_SENS_ID, V_HUM);
MyMessage msg_setting_led(SETTING_LED_SENS_ID, V_VAR1);
MyMessage msg_delay_time(DELAY_TIME_SENS_ID, V_VAR1);
MyMessage msg_battary_send(BATTARY_SEND_SENS_ID, V_VAR1);
MyMessage powerMsg(BATTARY_DATA_SENS_ID, V_VAR1);

void preHwInit()
{
  pinMode(led_pin, OUTPUT);
  digitalWrite(led_pin, OFF);
  pinMode(mode_pin, INPUT_PULLUP);
}

void before()
{
  set_led = loadState(100);
  if (set_led > 1) {
    set_led = 1;
    saveState(100, set_led);
  }
  delayTime = loadState(101);
  if (delayTime > 60) {
    delayTime = 3;
    saveState(101, delayTime);
  }
  send_batteryTime = loadState(102);
  if (send_batteryTime > 48) {
    send_batteryTime = 6;
    saveState(102, send_batteryTime);
  }


  digitalWrite(led_pin, ON);
}


void presentation()
{
  sendSketchInfo("Temp & Hum Sensor CR2477", "1.0");
  wait(100);
  present(TEMP_SENS_ID, S_TEMP, "TEMPERATURE DATA");
  wait(100);
  present(HUM_SENS_ID, S_HUM, "HUMIDITY DATA");
  wait(100);
  present(SETTING_LED_SENS_ID, S_CUSTOM, "LED MODE");
  wait(100);
  present(DELAY_TIME_SENS_ID, S_CUSTOM, "DELAY TIME/MIN");
  wait(100);
  present(BATTARY_SEND_SENS_ID, S_CUSTOM, "BATTERY SEND TIME/H");
  wait(100);
  present(BATTARY_DATA_SENS_ID, S_CUSTOM, "BATTERY DATA");
}

void setup()
{
  //attachInterrupt(0, configListener, RISING);
  digitalWrite(led_pin, OFF);
  wait(500);
  digitalWrite(led_pin, ON);
  wait(75);
  digitalWrite(led_pin, OFF);
  wait(50);
  digitalWrite(led_pin, ON);
  wait(75);
  digitalWrite(led_pin, OFF);
  wait(50);
  digitalWrite(led_pin, ON);
  wait(75);
  digitalWrite(led_pin, OFF);
  TRANSPORT_DEBUG(PSTR("MyS: OPERATING MODE\n"));
  wait(100);
  readBatLev();
  wait(100);
  sht20.initSHT20();
  wait(100);
  send_data();
  wait(100);
  send(msg_delay_time.set(delayTime));
  wait(100);
  send(msg_setting_led.set(set_led));
  wait(100);
  send(msg_battary_send.set(send_batteryTime));
}

void loop()
{
  if (configMode == 0) {



    if (sleep_flag == 0) {
      timer_status = sleep(digitalPinToInterrupt(mode_pin), FALLING, delayTime * 60 * 1000, false);
      //timer_status = sleep(digitalPinToInterrupt(mode_pin), RISING, delayTime * 60 * 1000, false);
      sleep_flag = 1;
    }
    if (timer_status == -1) {

      w_battetyTime = w_battetyTime + (delayTime * 60 * 1000);

      if (w_battetyTime >= send_batteryTime * 60 * 60 * 1000) {
        readBatLev();
        w_battetyTime = 0;
      }
      send_data();
      sleep_flag = 0;
    }
    if (timer_status == 0) {
      if (digitalRead(2) == LOW && flag_mode_button == 0) //  
      {
        flag_mode_button = 1;
        previousMillis = millis();
        wait(50);
      }
      if (digitalRead(2) == LOW && flag_mode_button == 1) {
        if ((millis() - previousMillis > 0) && (millis() - previousMillis <= 2000)) {
          if (millis() - lightMillis > 50)    {
            lightMillis = millis();
            digitalWrite(led_pin, !digitalRead(led_pin));
          }
        }
        if ((millis() - previousMillis > 2000) && (millis() - previousMillis <= 2500)) {
          digitalWrite(led_pin, OFF);
        }
        if ((millis() - previousMillis > 2500) && (millis() - previousMillis <= 4500)) {
          if (millis() - lightMillis > 25)    {
            lightMillis = millis();
            digitalWrite(led_pin, !digitalRead(led_pin));
          }
        }
        if (millis() - previousMillis > 4500) {
          digitalWrite(led_pin, OFF);
        }
      }
      if (digitalRead(2) == HIGH && flag_mode_button == 1) //   
      {
        if ((millis() - previousMillis > 0) && (millis() - previousMillis <= 2000)) {
          configMode = !configMode;
          flag_mode_button = 0;
          TRANSPORT_DEBUG(PSTR("MyS: CONFIGURATION MODE\n"));
          sleep_flag = 0;
          digitalWrite(led_pin, OFF);
        }
        if ((millis() - previousMillis > 2000) && (millis() - previousMillis <= 2500)) {
          flag_mode_button = 0;
          sleep_flag = 0;
        }
        if ((millis() - previousMillis > 2500) && (millis() - previousMillis <= 4500))
        {
          flag_mode_button = 0;
          sleep_flag = 0;
          digitalWrite(led_pin, OFF);
        }
        if (millis() - previousMillis > 4500) {
          flag_mode_button = 0;
          sleep_flag = 0;
          wait(50);
        }
      }
    }
  } else {
    if (listen_flag == 0) {
      RF24_startListening();
      listen_flag = 1;
    }
    if (millis() - lightMillis > 1000) {
      lightMillis = millis();
      digitalWrite(led_pin, !digitalRead(led_pin));
    }
    if (digitalRead(2) == LOW && flag_mode_button == 0) //  
    {
      flag_mode_button = 1;
      //previousMillis = millis();
      wait(50);
    }
    if (digitalRead(2) == LOW && flag_mode_button == 1) {
      
    }
    if (digitalRead(2) == HIGH && flag_mode_button == 1) //   
    {
       
      configMode = !configMode;
      listen_flag = 0;
      flag_mode_button = 0;
      TRANSPORT_DEBUG(PSTR("MyS: OPERATING MODE\n"));
      digitalWrite(led_pin, OFF);
      wait(50);
    }
  }
}



void receive(const MyMessage & message)
{
  if (message.sensor == SETTING_LED_SENS_ID) {
    if (message.type == V_VAR1) {
      if (message.getByte() <= 1) {
        set_led = message.getBool();
        saveState(100, set_led);
        send(msg_setting_led.set(set_led));
        if (set_led == 0) {
          TRANSPORT_DEBUG(PSTR("MyS: STATUS LED: OFF\n"));
        }
        if (set_led == 1) {
          TRANSPORT_DEBUG(PSTR("MyS: STATUS LED: ON\n"));
          if (set_led == 1) {
            digitalWrite(led_pin, ON);
            wait(50);
            digitalWrite(led_pin, OFF);
          }
        }
      }
    }
  }
  if (message.sensor == DELAY_TIME_SENS_ID) {
    if (message.type == V_VAR1) {
      if (message.getULong() <= 60 && message.getULong() != 0) {
        delayTime = message.getULong();
        saveState(101, delayTime);
        send(msg_delay_time.set(delayTime));
        TRANSPORT_DEBUG(PSTR("MyS: THE NEW INTERVAL TEMP&HUM SEND VALUE IS SET: %d MIN.\n"), delayTime);
        if (set_led == 1) {
          digitalWrite(led_pin, ON);
          wait(50);
          digitalWrite(led_pin, OFF);
        }
      } else if (message.getULong() > 60) {
        delayTime = 60;
        saveState(101, delayTime);
        send(msg_delay_time.set(delayTime));
        TRANSPORT_DEBUG(PSTR("MyS: THE NEW INTERVAL TEMP&HUM SEND VALUE IS SET: %d MIN.\n"), delayTime);
        if (set_led == 1) {
          digitalWrite(led_pin, ON);
          wait(50);
          digitalWrite(led_pin, OFF);
        }
      } else if (message.getULong() == 0) {
        delayTime = 1;
        saveState(101, delayTime);
        send(msg_delay_time.set(delayTime));
        TRANSPORT_DEBUG(PSTR("MyS: THE NEW INTERVAL TEMP&HUM SEND VALUE IS SET: %d MIN.\n"), delayTime);
        if (set_led == 1) {
          digitalWrite(led_pin, ON);
          wait(50);
          digitalWrite(led_pin, OFF);
        }
      }
    }
  }
  if (message.sensor == BATTARY_SEND_SENS_ID) {
    if (message.type == V_VAR1) {
      if (message.getULong() <= 168) {
        send_batteryTime = message.getULong();
        saveState(102, send_batteryTime);
        send(msg_battary_send.set(send_batteryTime));
        TRANSPORT_DEBUG(PSTR("MyS: THE NEW INTERVAL BATTERY SEND IS SET: %d HOUR\n"), send_batteryTime);
        if (set_led == 1) {
          digitalWrite(led_pin, ON);
          wait(50);
          digitalWrite(led_pin, OFF);
        }
      }
    }
  }
}

void send_data()
{
  humd = sht20.readHumidity();
  temp = sht20.readTemperature();
  int t_humd = (int)humd;
  int t_temp = (int)temp;
  if (abs(temp - oldtemp) >= tempThreshold) {
    send(msg_temp.set(temp, 1));
    oldtemp = temp;
    if (set_led == 1) {
      digitalWrite(led_pin, ON);
      wait(50);
      digitalWrite(led_pin, OFF);
    }
  }
  wait(100);
  if (abs(humd - oldhumd) >= humThreshold) {
    send(msg_hum.set(humd, 1));
    oldhumd = humd;
    if (set_led == 1) {
      digitalWrite(led_pin, ON);
      wait(50);
      digitalWrite(led_pin, OFF);
    }
  }
  TRANSPORT_DEBUG(PSTR("MyS: DATA - TEMPERATURE: %d, HUMIDITY %d\n"), t_temp, t_humd);
}


void readBatLev() {
  ADMUX = _BV(REFS1) | _BV(REFS0) | _BV(MUX0);
  wait(100);
  RF24_startListening();
  wait(200);
  ADCSRA |= _BV(ADSC);
  while (bit_is_set(ADCSRA, ADSC));
  uint8_t low  = ADCL;
  uint8_t high = ADCH;
  long temp = (high << 8) | low;
  float vcc = temp * 1.1 / 1023 * BAT_COOF * 100;
  battery = map((int)vcc, BAT_MIN, BAT_MAX, 0, 100);
  if (battery < 0) {
    battery = 0;
  }
  if (battery > 100) {
    battery = 100;
  }
  TRANSPORT_DEBUG(PSTR("MyS: BATTERY LEVEL: %d, PREVIUS BATTERY LEVEL: %d\n"), battery, old_battery);
  TRANSPORT_DEBUG(PSTR("MyS: BATTERY LEVEL ADC: %d\n"), temp);

  /*
    if (old_battery != battery) {
      if (battery < old_battery) {
        old_battery = battery;
        wait(100);
        sendBatteryLevel(battery);
        wait(100);
        send(powerMsg.set(temp));
        TRANSPORT_DEBUG(PSTR("MyS: SEND BATTERY LEVEL\n"));
      } else {
        battery = old_battery;
      }
    }
  */
  wait(100);
  sendBatteryLevel(battery);
  wait(100);
  send(powerMsg.set(temp));
  TRANSPORT_DEBUG(PSTR("MyS: SEND BATTERY LEVEL\n"));
}


:


:


( ), Mysensors( Mysensors )



. , , , 3d www.openhardware.io. , Mysensors — t.me/mysensors_rus.

Source: https://habr.com/ru/post/de452234/


All Articles