Hoy quiero compartir uno de mis proyectos Arduino. Érase una vez, no hace mucho tiempo, en algún lugar de Internet, me enteré de Arduino. Me uní a este negocio bastante rápido, el nivel de entrada no es alto. Después de un tiempo, después de haber recogido un montón de sensores, los sensores para un hogar inteligente comenzaron a sorprenderme pensando que de alguna manera todo estaba fuera de mi mente.
Módulos, grandes cajas lisas, un montón de cables y pegamento caliente :). Al mirar mi caja con un sensor de temperatura y, por ejemplo, el sensor de temperatura del mismo Xiaomi, me di cuenta de que me gustaría que se pareciera a Xiaomi, pero al mismo tiempo podría reprogramarlo como el mío en una caja de 10 cm por 6 cm con cables y adhesivo termofusible. Y probablemente entonces se estableció el comienzo de mis proyectos de bricolaje arduino en placas de PCB.
En el artículo de hoy, hablaremos sobre un sensor de temperatura y humedad basado en el procesador atmega328p-mu. Esta es una versión "más pequeña" (un análogo absoluto) del procesador atmega328p-au (Arduino Uno, Pro Mini, Nano) conocido por todos los desarrolladores de arduino. Si alguien ha leído mis artículos antes, saben que prefiero Mysensors. Que es esto Esta es una biblioteca muy simple y bien diseñada y, lo que es importante, bien descrita para Arduino IDE (y no solo) para crear redes de radio IOT a frecuencias de 2.4 GHz, 915, 868, 433 MHz, así como redes cableadas en la interfaz 485, tal vez no todas mencionadas El protocolo está en constante evolución, se agrega algo todo el tiempo.
Lo primero que se hizo fue el sensor en la placa PCB. Lo hice sin mirar el estuche, de acuerdo con el principio, lo principal es hacer el sensor y el estuche de alguna manera lo imprimiré ... sí, no hagas eso :). De hecho, el sensor en sí es el mismo Arduinka Pro Mini, el módulo de radio nRF24l01, el sensor de temperatura y humedad SHT20, solo que sin cables ni pegamento caliente. De las "campanas y silbatos", esta es una unidad flash SPI externa para flashear por el aire (se requiere el cargador de arranque DualOptibut para la operación, luego dejé de ponerlos (unidades flash) en los paquetes de circuitos, ya que no hay firmware en el aire y la mitad de la batería) y el "cripto micrófono" ATSHA204A, por así decirlo, por completo kit de hardware (en Mysensors, para activar firmas, cifrado, etc., solo necesita especificar el #def necesario al comienzo del boceto).

La placa en sí se hizo en el programa Diptrace, después de ver los videos tutoriales en YouTube, al principio parecía algo "infernal", pero en realidad resultó no ser tan difícil. Pedí tableros en China en jlcpcb.com, 2 dólares, de cualquier color, y después de 2 semanas ya tienes 10 piezas de "tu propia creación" en tus manos :).


El siguiente paso fue el desarrollo del cuerpo. Oh, esto resultó ser el mismo problema. En general, no busqué formas fáciles, decidí dominar Solid Works. Al final resultó que, esto no es para nada como con Deeptrace. Sin embargo, recomiendo este editor para estudiar. El proceso de aprendizaje duró un mes de ver videos en YouTube y repetir la lección en el editor. En el proceso de desarrollo del caso, quedó claro que hacer una placa de dispositivo sin tener en cuenta los parámetros del caso futuro es una mala decisión, de la serie insertamos los palos en nuestras propias ruedas. Según los resultados de las versiones de la placa, salieron tres, teniendo en cuenta la instalación de la placa en el caso, y creo que esta no es la última opción.
Al comienzo del desarrollo del edificio, la idea era imprimirlo en una impresora 3D FDM, pero cuanto más se adentraba en el bosque, más claro estaba que no podía reproducir toda mi lista de deseos. Cuando llegó este entendimiento, ya aprendí sobre otra tecnología de impresión 3D: SLA. Sin pensarlo dos veces e impresionado con la calidad de impresión, se emitió la lista de deseos de Ali -
ANYCUBIC Photon . (Enlace ana Ali, no publicidad, no afiliación, ... solo un enlace).
Escribiré de inmediato, ahora, basado en mi experiencia al momento de escribir esto, ... ¡oh, este milagro es genial! El caso, que fue diseñado en el editor, por supuesto, no se imprimió por primera vez y hubo muchas mejoras. Bueno, probablemente no sea al revés. Como resultado, obtuve el resultado que quería. Todo un dispositivo en miniatura, un buen estuche de bricolaje con detalles muy precisos, botones, fuentes, todo lo representado en la cabeza. Se agregó un imán a la cubierta posterior, ahora se puede montar fácilmente en superficies de hierro.








Estos son intentos de imprimir el mismo modelo en una impresora FDM:


Como el dispositivo resultó ser pequeño, pero sigue siendo un arduinka, me sorprendió la salida de conectores en miniatura para la programación. Y, en consecuencia, se hizo un pequeño adaptador para los conectores para una conexión conveniente con el programador y el convertidor TTL.

Todo se compró en Ali (sí, no solo hay módulos arduino completos)
Condensador de tantalio SMD 4.7uF - 4.7uF | 10v | 10% - C1
Condensador de cerámica SMD 100nF | Y5V - 100nF | 50v | + 80-20% - C2, C3, C4, C5, C6, C7
LED - LADO LED - D1
Pin Header Female - 2x3P | 6pin | 1.27 mm - J1, J2
Resistencia SMD 20K Ohm - 20K | 5% - R1
Resistencia SMD 4.7K Ohm - 4.7K | 5% - R2, R3, R4
Resistencia SMD 470K Ohm - 470 | 1% - R5
Resistencia SMD 1M Ohm - 1M | 1% - R6
Resistencia SMD 18K Ohm - 18K | 5% - R7
Resistencia SMD 10K Ohm - 10K | 5% - R8
Botón lateral SMD de 4 pines - SW1, SW2
512-Kbit, 1.65V SPI Memoria Flash Serial - AT25DF512C-SSHN-B - U1
Mini NRF24L01 + 2.4GHz 1.27MM RF - nRF24l01 1.27 SMD - U2
ATMEGA328P-MU QFN32 - U3
AUTENTICACIÓN DE CRIPTO, 1 HILO - ATSHA204A-STUCZ-T - U4
Sensor de humedad y temperatura IC - SHT20 - U5
SOPORTE DE BATERÍA PARA CR2477-1 - L-KLS5-CR2477-1 - U6
El código del programa es bastante simple. Se usó un ejemplo de la biblioteca DFRobot para trabajar con el sensor SHT20. En principio, cualquier boceto, para cualquier sensor, puede convertirse en un boceto para trabajar en la red Mysensors en 5 minutos.
Listado de código#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.