Aujourd'hui, je veux partager l'un de mes projets Arduino. Il était une fois, il n'y a pas très longtemps, quelque part sur Internet, j'ai découvert Arduino. J'ai rejoint cette entreprise assez rapidement, le niveau d'entrée n'y est pas élevé. Après un certain temps, après avoir déjà collecté un tas de capteurs, les capteurs d'une maison intelligente ont commencé à me surprendre en pensant que tout cela était hors de l'esprit.
Modules, grandes boîtes unies, un tas de fils et de la colle chaude :). En regardant ma boîte avec un capteur de température et, par exemple, le capteur de température du même Xiaomi, j'ai réalisé que je voudrais qu'elle ressemble à Xiaomi, mais en même temps que vous pouviez la reprogrammer comme la mienne dans une boîte de 10 cm par 6 cm avec des fils et de la colle thermofusible. Et probablement le début de mes projets DIY Arduino sur des cartes PCB a été posé.
Dans l'article d'aujourd'hui, nous parlerons d'un capteur de température et d'humidité basé sur le processeur atmega328p-mu. Il s'agit d'une version «plus petite» (un analogue absolu) du processeur atmega328p-au (Arduino Uno, Pro Mini, Nano) connue de tous les développeurs Arduino. Si quelqu'un a déjà lu mes articles, il sait que je préfère Mysensors. Qu'est ce que c'est Il s'agit d'une bibliothèque très simple et bien conçue et, ce qui est important, bien décrite pour Arduino IDE (et pas seulement) pour créer des réseaux radio IOT à des fréquences de 2,4 GHz, 915, 868, 433 MHz, ainsi que des réseaux câblés sur l'interface 485, peut-être pas tous mentionnés Le protocole évolue constamment, quelque chose est ajouté tout le temps.
La première chose qui a été faite a été le capteur lui-même sur la carte PCB. Je l'ai fait sans regarder le boîtier, selon le principe, l'essentiel est de fabriquer un capteur, et je vais imprimer le boîtier en quelque sorte ... ouais, ne le fais pas :) En fait, le capteur lui-même est le même Arduinka Pro Mini, le module radio nRF24l01, le capteur de température et d'humidité SHT20, uniquement sans fils et colle chaude. Parmi les «cloches et sifflets», il s'agit d'un lecteur flash SPI externe pour flasher dans les airs (le chargeur de démarrage DualOptibut est requis pour fonctionner, plus tard j'ai cessé de les mettre (lecteurs flash) sur les circuits imprimés, car il n'y a pas de firmware sur l'air et la moitié de la batterie) et le «micro crypto» ATSHA204A, pour ainsi dire, pour le plein kit matériel (dans Mysensors, pour activer les signatures, le chiffrement, etc., il vous suffit de spécifier le #def nécessaire au début du croquis).

La carte elle-même a été créée dans le programme Diptrace, après avoir regardé les didacticiels vidéo sur YouTube, au début, cela semblait être quelque chose "d'enfer", mais en réalité, cela ne s'est pas avéré si difficile. J'ai commandé des planches en Chine sur jlcpcb.com, 2 dollars, n'importe quelle couleur, et après 2 semaines, vous avez déjà 10 pièces de «votre propre création» en main :).


L'étape suivante a été le développement du corps. Oh, cela s'est avéré être le même problème. En général, je n'ai pas cherché de voies faciles, j'ai décidé de maîtriser le Solid Works. Il s'est avéré que ce n'est pas du tout le cas avec Deeptrace. Néanmoins, je recommande cet éditeur pour étude. Le processus d'apprentissage a duré un mois en regardant tranquillement des leçons vidéo sur YouTube et en répétant la leçon dans l'éditeur. Au cours du développement du boîtier, il est devenu clair que la fabrication d'une carte d'appareil sans tenir compte des paramètres du futur boîtier est une mauvaise décision, de la série où nous insérons les bâtons dans nos propres roues. Selon les résultats des versions de la carte, trois sont sorties, en tenant compte de l'installation de la carte dans le boîtier, et je pense que ce n'est pas la dernière option.
Au début du développement du bâtiment, l'idée était de l'imprimer sur une imprimante FDM 3D, mais plus il s'avançait dans la forêt, plus il devenait clair qu'il n'était pas en mesure de reproduire toute ma liste de souhaits. Au moment où cette compréhension est arrivée, j'avais déjà appris l'existence d'une autre technologie d'impression 3D - SLA. Sans réfléchir et impressionné par la qualité d'impression, la liste de souhaits sur Ali -
ANYCUBIC Photon a été publiée. (Lien ana Ali, pas de publicité, pas d'affiliation, ... juste un lien).
J'écrirai tout de suite, maintenant, sur la base de mon expérience au moment de la rédaction de ce document, ... oh, cette chose cool est une chose cool !!! Le cas qui a été conçu dans l'éditeur bien sûr et a été imprimé pas la première fois et il y a eu beaucoup d'améliorations. Eh bien, ce n'est probablement pas l'inverse. En conséquence, j'ai obtenu le résultat que je voulais. Un appareil miniature, un bon étui de bricolage avec des détails très précis, des boutons, des polices, tout comme représenté dans la tête. Un aimant a été ajouté au couvercle arrière, maintenant il peut être facilement monté sur des surfaces en fer.








Ce sont des tentatives d'imprimer le même modèle sur une imprimante FDM:


Puisque l'appareil s'est avéré être petit, mais c'est toujours un arduinka, j'ai été intrigué par la sortie de connecteurs miniatures pour la programmation. Et en conséquence, un petit adaptateur a été conçu pour les connecteurs pour une connexion pratique avec le programmateur et le convertisseur TTL.

Tout a été acheté sur Ali (oui, il n'y a pas que des modules Arduino complets)
Condensateur CMS au tantale 4.7uF - 4.7uF | 10v | 10% - C1
Condensateur céramique CMS 100nF | Y5V - 100nF | 50v | + 80-20% - C2, C3, C4, C5, C6, C7
LED - LED SIDE - D1
Embase à broches femelle - 2x3P | 6pin | 1,27 mm - J1, J2
Résistance CMS 20K Ohm - 20K | 5% - R1
Résistance CMS 4.7K Ohm - 4.7K | 5% - R2, R3, R4
Résistance CMS 470K Ohm - 470 | 1% - R5
Résistance CMS 1M Ohm - 1M | 1% - R6
Résistance CMS 18K Ohm - 18K | 5% - R7
Résistance CMS 10K Ohm - 10K | 5% - R8
Bouton latéral SMD à 4 broches - SW1, SW2
Mémoire flash série SPI 512 Kbit, 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
AUTHENTIFICATION CRYPTO, 1 FIL - ATSHA204A-STUCZ-T - U4
IC capteur d'humidité et de température - SHT20 - U5
SUPPORT DE BATTERIE POUR CR2477-1 - L-KLS5-CR2477-1 - U6
Le code du programme est assez simple. Un exemple de la bibliothèque DFRobot a été utilisé pour travailler avec le capteur SHT20. En principe, n'importe quel croquis, pour n'importe quel capteur, peut être transformé en croquis pour travailler dans le réseau Mysensors en 5 minutes.
Liste des codes#include <Wire.h>
#include "DFRobot_SHT20.h"
DFRobot_SHT20 sht20;
#define MY_DEBUG
#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 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;
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()
{
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);
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;
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);
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.