SMS-мониторинг веса трех ульев за 33$

NewBee

Здравствуйте! Позади пол-года с момента, как я занялся темой весов для пасечников.

Три месяца назад была опубликована статья на Хабр-е о первой удачной системе.

Что-же произошло с весами за этот квартал, не считая второй версии и перепробованных 7 аппаратных конфигураций?

Для простоты(и для тех, кто не читал предыдущие публикации) перечислю возможности системы:

  1. После заката солнца, измеряется вес ульев, дельта за сутки и от момента включения/сброса отправляется в виде смс.

  2. Дополнительно включена информация о мощности сигнала сотовой сети и уровне заряда батареи.

  3. Реализована функция оповещения о вылетевшем рое и действиях злоумышленников (снятой крышке улья).

Максимальный вес ульев составляет 200кг.

Ничего этого не было-бы без помощи в виде испытаний/критики со стороны пчеловодов, а также понимания и поддержки со стороны жены Светланы.

В итоге, как мне кажется, упростить систему уже весьма затруднительно, и от одних только датчиков веса больше информации получить нереально!

Данная статья содержит информацию, поданую в формате “Cделай-Cам” о сборке системы.

Итак, если Вас не страшат пол-сотни точек пайки, и еще остались школьные знания по трудам и физике/информатике(а ведь учителя говорили – что пригодятся в жизни ;-), тогда вперед!

Нам понадобится следующий набор оборудования/материалов:

  1. Arduino Pro Mini 3V
    Следует обратить внимание на микросхему линейного преобразователя – она должна быть именно на 3.3В – на чипе маркировки KB 33/LB 33/DE A10 – у меня китайцы что-то напутали, и вся партия
    плат в магазине оказалась с 5-вольтовыми регуляторами и кварцами на 16MHz.
  2. USB-Ttl на чипе CH340 – можно даже 5-вольтовый, но тогда во время прошивки микроконтроллера, Arduino нужно будет отключать от GSM-модуля, чтобы не сжечь последний.
    Платы на чипе PL2303 не работают под Windows 10.
  3. Модуль связи GSM Goouu Tech IOT GA-6-B или AI-THINKER A-6 Mini.
  4. 10-см. отрезок обычного электрического провода(ШВВП), 0.75мм в изоляции (для антенны)
  5. Стартовый пакет оператора, имеющего хорошее покрытие в месте расположения Вашей пасеки.
    Да, пакет надо предварительно активировать в обычном телефоне, ОТКЛЮЧИТЬ ЗАПРОС PIN при входе, и пополнить счет.
  6. провод dupont 20см мама-мама – 4 шт. (для подключения Arduino к USB-TTL)
  7. 3шт. HX711 – АЦП для весов
  8. 6 тензодатчиков на вес до 50кг
  9. 6 метров 4-жильного телефонного кабеля – для соединения модулей веса с ARDUINO.
  10. 5 метров 6-жильного плоского телефонного кабеля ШТЛП (можно взять компьютерную витую пару UTP) для соедиения микроконтроллера с модулем связи.
  11. Фоторезистор GL5528 (важно именно такой, с темновым сопротивлением 1МОм и световым 10-20кОм).
  12. две пары разьемов и гнезд 6P6C – телефонные, гнезда – с “хвостами”
  13. 50см двухстороннего скотча шириной 10мм – для крепления солнечной батареи к корпусу GSM-модуля и компонентов внутри.
  14. Плата зарядного устройства на базе TP4056 для LiIon батарей
  15. Держатель батарей 18650 и, собственно, сама батарея.
  16. Немного воска или парафина(свеча-таблетка аромалампы) – для влагозащиты HX711
  17. Отрезок деревянного бруса 25х50х450мм для основания тензодатчиков.
  18. Дюжина саморезов с прессшайбой 4,2х19 мм для крепления датчиков к основанию.
  19. Солнечная батарея 5/6V 1W
  20. Распределительная коробка под модуль связи и солнечную батарею(размер 60×100мм) – я брал Spelsberg 130х85х37 (i16)
  21. Двух/трехпозиционный переключатель 3A/250V для крепления в круглое отверстие :
    Выключатель

Готовый к сборке комплект выглядит следующим образом:

Набор

Кроме этого, потребуются некривые руки, паяльник ЭПСН-25, канифоль и припой ПОС-60.

Для столярных работ достаточно ножовки по дереву/металлу, стамески и дрели со сверлами 3 и 6мм.

Компоновка системы у нас следующая:

Компоновка

В любом случае, не стоит располагать GSM-модуль ближе метра от Arduino – при высокой мощности сигнала в стандарте GSM900 это может вызывать перезагрузку микроконтроллера!

Оптимальной будет установка модуля связи на шесте/брусе на высоте 2м, ориентация солнечной панели – на юг.

Теперь приступим к сборке:

GSM A6

Для начала, выпаиваем из GSM-модуля два светодиода (место, где они находились обведено оранжевым овалом)
Сим-крту вставляем контактными площадками к печатной плате, скошенный уголок на фото обозначен стрелкой.

Плюс от батареи и провода, идущего к контроллеру паяется к конденсатору напрямую (4).

Дело в том, что сам модуль связи требует для своего питания 3.4-4.2В, а его контакт 5V заведен на понижающий преобразователь step-down, поэтому для работы от li-ion напряжение надо подавать минуя эту часть цепи.

Arduino Pro Mini 3v

Дальше аналогичную процедуру проводим со светодиодом на плате Arduino (овал справа от квадратного чипа),
Паяем гребенку на четыре контакта (1), обязательно горизонтально – вдоль платы.

Теперь необходимо взять 5 метров телефонного шестижильного кабеля, распределительную коробку, модули GSM и зарядки (TP4056), фоторезистор, держатель батареи, солнечную панель и выключатель.

Эти компоненты собираются/паяются согласно компоновке и схеме в начале статьи (цвета проводов соответствуют действительности).

Держатель батареи, модуль связи и зарядки в отсеке крепятся на двухсторонний скотч.

Паяем нашу антенну из провода:

ArduinoOUTSIDE

Как ни парадоксально, но с ней сигнал лучьше на 1-2 dBm, чем вот с такой:

ChinaANT

Все отверстия герметизируются термо/клеем.

Ответную часть кабеля распаиваем на arduino.

Все остальное сделаем немного позже.

А вот теперь мы на некоторое время отвлечемся от паяльника, и перейдем к программной части.
Буду описывать последовательность действий для Windows:
Во-первых, необходимо скачать и установить/распаковать программу Arduino IDE – текущая версия – 1.8.9, но я пользуюсь 1.6.4

Для простоты распаковываем архив в папку C:\arduino-“номерВашейверсии”, внутри у нас будут папки /dist, drivers, examples, hardware, java, lib, libraries, reference, tools, а также исполняемый файл arduino (помимо прочих).

Теперь нам потребуется библиотека для работы с АЦП HX711 – зеленая кнопка “clone or download” – download ZIP.

В результате бурной работы программистов не все версии данной библиотеки корректно компиллируются с используемыми мной функциями, поэтому продублировал рабочую у себя:

beefree.xyz/wp-content/uploads/2019/07/HX711-master.zip

Содержимое (папка HX711-master) ложится в каталог C:\arduino-“номерВашейверсии”\libraries

Ну и конечно-же драйвер для USB-TTL с того-же github – из распакованного архива просто запускается инсталяха файлом SETUP.

Запускаем и настраиваем программу C:\arduino-“номерВашейверсии”\arduino

Интерфейс программы

Заходим в пункт “Инструменты”-выбираем плату “Arduino Pro or Pro Mini” , процессор Atmega 328 3.3V 8 MHz , порт – номер кроме системного COM1 (он появляется после установки драйвера CH340 при подключенном USB-TTL адаптере)

Ок, копируем нижеследующий скетч (программу), и вставляем ее в окно Arduino IDE

char phone_no[]="+123456789012"; // Your phone number that receive SMS with counry code 

byte pin2sleep=5; //  Set powerON/OFF pin

// NeverSleep (only gsm in power-off mode)

#include <SoftwareSerial.h> // Sofrware serial library
#include "HX711.h" // HX711 lib. https://github.com/bogde/HX711 or beefree.xyz/wp-content/uploads/2019/07/HX711-master.zip
#include <EEPROM.h> // EEPROM lib.

HX711 scale0(7, 14);
HX711 scale1(8, 14);
HX711 scale2(9, 14);
#define SENSORCNT 3
HX711 *scale[SENSORCNT];

SoftwareSerial mySerial(4, 3); // Set I/O-port TXD, RXD of GSM-shield

float delta00; // delta weight from start
float delta10;
float delta20;
float delta01; // delta weight from yesterday
float delta11;
float delta21;

float raw00; //raw data from sensors on first start
float raw10;
float raw20;
float raw01; //raw data from sensors on yesterday
float raw11;
float raw21;
float raw02; //actual raw data from sensors
float raw12;
float raw22;


float swarm0w; //weight data for swarm warning
float swarm1w;
float swarm2w;
float w0; //weight data for swarm warning
float w1;
float w2;
float DeltaW=0;

unsigned long swarm0t; //time for swarm warning
unsigned long swarm1t;
unsigned long swarm2t;

unsigned long TimeNow;

word calibrate0=20880; //calibration factor for each sensor
word calibrate1=20880;
word calibrate2=20880;


word daynum=0; //numbers of day after start

word i;

int notsunset=0;
int Hwarning=0;
int Halarm=0;


boolean setZero=false;

char ch = 0;
char ch1 = 0;
char ch2 = 0;
char ch3 = 0;
char ch4 = 0;

char csq = 0;
char csq1 = 0;
char csq2 = 0;
char csq3 = 0;
char csq4 = 0;

void readVcc() // read battery capacity 
{
  ch = mySerial.read();
   while (mySerial.available() > 0) {  ch = mySerial.read(); } // empty input buffer from modem

 mySerial.println("AT+CBC?"); //ask gprs for battery status
// delay(200);
for ( i = 0; i <= 20 ; i++) { delayMicroseconds(10000);}
 while (mySerial.available() > 0) { //read input string between coma and CR
 ch = mySerial.read();
     if (ch ==','){ 
       ch1 = mySerial.read();
       ch2 = mySerial.read();
       ch3 = mySerial.read();
       ch4 = mySerial.read();       
     }
   }
}

void SignalQ() // read signal strenght 
{
  csq = mySerial.read();
   while (mySerial.available() > 0) {  csq = mySerial.read(); } // empty input buffer from modem

 mySerial.println("AT+CSQ"); //ask gprs for battery status
// delay(200);
for ( i = 0; i <= 20 ; i++) { delayMicroseconds(10000);}
 while (mySerial.available() > 0) { //read input string between coma and CR
 csq = mySerial.read();
     if (csq ==':'){ 
       csq1 = mySerial.read();
       csq2 = mySerial.read();
       csq3 = mySerial.read();
       csq4 = mySerial.read();       
     }
   }
}

void Walert() //send swarm/intrusion alert
{
digitalWrite(pin2sleep, LOW); // Turn ON modem
  delay(21000); // Wait for modem booting

  mySerial.println("AT+CMGF=1");    //  Part of SMS sending 
  delay(2000);
  mySerial.print("AT+CMGS=\"");
  mySerial.print(phone_no); 
  mySerial.write(0x22);
  mySerial.write(0x0D);  // hex equivalent of Carraige return    
  mySerial.write(0x0A);  // hex equivalent of newline
  delay(2000);

   if (Hwarning != 0) // warning about hive invasion
   {
    mySerial.println("WARNING!!!"); 
    mySerial.print("Hive  "); 
    mySerial.print(Hwarning);
    mySerial.println("  is opened! "); 
  }

  if (Halarm != 0)
   {
    mySerial.println("ALARM!!!");  // alarm about swarm
    mySerial.print("Bees in hive  "); 
    mySerial.print(Halarm);
    mySerial.println("  is SWARMING!!! "); 
  }

   mySerial.println (char(26));//the ASCII code of the ctrl+z is 26
  delay(7000);

  digitalWrite(pin2sleep, HIGH); // Turn OFF GSM-shield
  delay(2200);
  digitalWrite(pin2sleep, LOW); // Turn OFF GSM-shield
  delay(2200);
  digitalWrite(pin2sleep, HIGH);
Hwarning=0;
Halarm=0;
DeltaW=0;
for (int i = 0; i <= 24; i++) { //blinking LED13 on reset/first boot
    digitalWrite(13, HIGH);
    delay(250);
    digitalWrite(13, LOW);
    delay(250);
  }
  }

void nolighting() // disable false statistic when night lighting flash
{
  detachInterrupt(digitalPinToInterrupt(0));

   for ( i=0; i <= 250; i++){
      delayMicroseconds(10000);
   }

//  attachInterrupt(0, nolighting , FALLING); // Interrupt by LOW level
  attachInterrupt(0, SendStat , RISING); // Interrupt by HIGH level
}

// **********************************************************************
void SendStat() //send weight
{

  detachInterrupt(digitalPinToInterrupt(0));


 notsunset=0;
// for ( i=0; i <= 250; i++){
//      if ( !digitalRead(2) ){ notsunset++; } //is a really sunset now? you shure?
//      delayMicroseconds(1000);
//   }

  if ( notsunset==0 )
  { 

  scale0.power_up(); //power up all scales 
  scale1.power_up();
  scale2.power_up();

    digitalWrite(13, HIGH);  

digitalWrite(pin2sleep, LOW); // Turn ON modem
for ( i = 0; i <= 2100 ; i++) { delayMicroseconds(10000);}

  raw01=raw02;
  raw11=raw12;
  raw21=raw22;
  raw02=scale0.get_units(240); //warm-up Wheatstone bridges and hx711-s
  raw02=scale0.get_units(20); //read data from scales
  raw12=scale1.get_units(20);
  raw22=scale2.get_units(20);

  daynum++; 
  delta00=(raw02-raw00)/calibrate0; // calculate weight changes 
  delta01=(raw02-raw01)/calibrate0;
  delta10=(raw12-raw10)/calibrate1;
  delta11=(raw12-raw11)/calibrate1; 
  delta20=(raw22-raw20)/calibrate2;
  delta21=(raw22-raw21)/calibrate2;

  readVcc(); 
  SignalQ();

//  delay(200);
  for ( i = 0; i <= 20 ; i++) { delayMicroseconds(10000);}
  mySerial.println("AT+CMGF=1");    //  Part of SMS sending 
  //delay(2000);
    for ( i = 0; i <= 200 ; i++) { delayMicroseconds(10000);}
  mySerial.print("AT+CMGS=\"");
  mySerial.print(phone_no); 
  mySerial.write(0x22);
  mySerial.write(0x0D);  // hex equivalent of Carraige return    
  mySerial.write(0x0A);  // hex equivalent of newline
//  delay(2000);
    for ( i = 0; i <= 200 ; i++) { delayMicroseconds(10000);}
  mySerial.print("Turn ");
  mySerial.println(daynum);
  mySerial.print("Hive1  ");
  mySerial.print(delta01);
  mySerial.print("   ");
  mySerial.println(delta00);
  mySerial.print("Hive2  ");
  mySerial.print(delta11);
  mySerial.print("   ");
  mySerial.println(delta10);
  mySerial.print("Hive3  ");
  mySerial.print(delta21);
  mySerial.print("   ");
  mySerial.println(delta20);


  mySerial.print("Battery capacity is ");
  mySerial.print(ch1);
  mySerial.print(ch2);
  mySerial.print(ch3);
  mySerial.print(ch4);
  mySerial.println(" %");
  mySerial.print("GSM signal strenght:  ");
  mySerial.print(csq1);
  mySerial.print(csq2);
  mySerial.print(csq3);
  if (csq4 != ',') {mySerial.print(csq4);}
  mySerial.println(" of 31");
  mySerial.println (char(26));//the ASCII code of the ctrl+z is 26
  for ( i = 0; i <= 700 ; i++) { delayMicroseconds(10000);}

  }


digitalWrite(pin2sleep, HIGH); // Turn OFF GSM-shield
    for ( i = 0; i <= 220 ; i++) { delayMicroseconds(10000);}
  digitalWrite(pin2sleep, LOW); // Turn OFF GSM-shield
    for ( i = 0; i <= 220 ; i++) { delayMicroseconds(10000);}
  digitalWrite(pin2sleep, HIGH);
  scale0.power_down(); //power down all scales 
  scale1.power_down();
  scale2.power_down();
  attachInterrupt(0, SendStat , RISING); // Interrupt by HIGH level
//  attachInterrupt(0, nolighting , FALLING); // Interrupt by LOW level

}
// *************************************************************************************************

void switchto9600()
{
mySerial.begin(115200); // Open software serial port
delay(16000); // wait for boot
mySerial.println("AT");
delay(200);
mySerial.println("AT");
delay(200);
mySerial.println("AT+IPR=9600");    //  Change Serial Speed 
delay(200);
mySerial.begin(9600);
mySerial.println("AT&W0");
delay(200);
mySerial.println("AT&W");
}

void setup() { // Setup part run once, at start

scale[0] = &scale0; //init scale
scale[1] = &scale1;
scale[2] = &scale2;

scale0.set_scale();
scale1.set_scale();
scale2.set_scale();

  pinMode(13, OUTPUT);  // Led pin init
  pinMode(pin2sleep, OUTPUT);// Init ON/OFF pin for GSM
  pinMode(2, INPUT_PULLUP); // Set pullup voltage
  Serial.begin(9600);

digitalWrite(pin2sleep, LOW); // Turn ON modem
  delay(21000); // Wait for modem booting


// -------------------------------------------------------------------------------

switchto9600(); //for AiThinker GSM A6

// -------------------------------------------------------------------------------

mySerial.begin(9600);

delay(200);

setZero=digitalRead(2);

//if (EEPROM.read(500)==EEPROM.read(501) || setZero) // first boot/reset with hiding photoresistor
if (setZero)
{
raw02=scale0.get_units(240); //warm-up Wheatstone bridges and hx711-s
raw00=scale0.get_units(20); //read data from scales
raw10=scale1.get_units(20);
raw20=scale2.get_units(20);

EEPROM.put(500, raw00); //write data to eeprom
EEPROM.put(504, raw10);
EEPROM.put(508, raw20);
for (int i = 0; i <= 24; i++) { //blinking LED13 on reset/first boot
    digitalWrite(13, HIGH);
    delay(500);
    digitalWrite(13, LOW);
    delay(500);
  }
}
else {
EEPROM.get(500, raw00); // read data from eeprom after battery change
EEPROM.get(504, raw10);
EEPROM.get(508, raw20);
digitalWrite(13, HIGH); // turn on LED 13 on 12sec. 
    delay(12000);
digitalWrite(13, LOW);
}

delay(200); // Test SMS at initial boot

readVcc();
SignalQ();
delay(200);
  mySerial.println("AT+CMGF=1");    
  delay(2000);
  mySerial.print("AT+CMGS=\"");
  mySerial.print(phone_no); 
  mySerial.write(0x22);
  mySerial.write(0x0D);  // hex equivalent of Carraige return    
  mySerial.write(0x0A);  // hex equivalent of newline
  delay(2000);
  mySerial.println("INITIAL BOOT OK");

  mySerial.print("Battery capacity is ");
  mySerial.print(ch1);
  mySerial.print(ch2);
  mySerial.print(ch3);
  mySerial.print(ch4);
  mySerial.println(" %");
  mySerial.print("GSM signal strenght:  ");
  mySerial.print(csq1);
  mySerial.print(csq2);
  mySerial.print(csq3);
  if (csq4 != ',') {mySerial.print(csq4);}
  mySerial.println(" of 31");
  mySerial.println (char(26));//the ASCII code of the ctrl+z is 26
  delay(7000);

raw02=raw00;
raw12=raw10;
raw22=raw20;



digitalWrite(pin2sleep, HIGH); // Turn OFF GSM-shield
  delay(2200);
  digitalWrite(pin2sleep, LOW); // Turn OFF GSM-shield
  delay(2200);
  digitalWrite(pin2sleep, HIGH);

////////////////////////////

swarm0w=scale0.get_units(3);
swarm0w=scale0.get_units(3);
swarm0w=scale0.get_units(8); //set initial data for swarm warning
swarm0t=millis();             // set initial time for swarm warning
swarm1w=scale1.get_units(8);
swarm1t=millis();
swarm2w=scale2.get_units(8);
swarm2t=millis();

///////////////////////////
  scale0.power_down(); //power down all scales 
  scale1.power_down();
  scale2.power_down();

attachInterrupt(0, SendStat , RISING); // Interrupt by HIGH level
// attachInterrupt(0, nolighting , FALLING); // Interrupt by LOW level
}

void loop() {
delay(30000);
delay(30000);

  scale0.power_up(); //power up all scales 
  scale1.power_up();
  scale2.power_up();

w0=scale0.get_units(3);
w0=scale0.get_units(3);
w0=scale0.get_units(8); //read data from scales
w1=scale1.get_units(8);
w2=scale2.get_units(8);

  scale0.power_down(); //power down all scales 
  scale1.power_down();
  scale2.power_down();

TimeNow=millis();

// check Hive 1 swarming or intrusion

DeltaW=((swarm0w-w0)/calibrate0);
if (TimeNow-swarm0t > 600000 ) 
{
  swarm0t=TimeNow;
  swarm0w=w0;
}
  else
    {
    if (DeltaW > 5 ) 
      {
        Hwarning=1; 
        Walert();
        swarm0t=TimeNow;
        swarm0w=w0;
       }
        else {if (DeltaW > 1 ) 
        {
         Halarm=1; 
         Walert();
         swarm0t=TimeNow;
         swarm0w=w0;
        }
      }
  }

// check Hive 2 swarming or intrusion

  DeltaW=((swarm1w-w1)/calibrate1);
if (TimeNow-swarm1t > 600000 ) 
{
  swarm1t=TimeNow;
  swarm1w=w1;
}
  else
    {
    if (DeltaW > 5 ) 
      {
        Hwarning=2; 
        Walert();
        swarm1t=TimeNow;
        swarm1w=w1;
       }
        else {if (DeltaW > 1 ) 
        {
         Halarm=2; 
         Walert();
         swarm1t=TimeNow;
         swarm1w=w1
         ;
        }
      }
  }

// check Hive 3 swarming or intrusion

 DeltaW=((swarm2w-w2)/calibrate2);
if (TimeNow-swarm2t > 600000 ) 
{
  swarm2t=TimeNow;
  swarm2w=w2;
}
  else
    {
    if (DeltaW > 5 ) 
      {
        Hwarning=3; 
        Walert();
        swarm2t=TimeNow;
        swarm2w=w2;
       }
        else {if (DeltaW > 1 ) 
        {
         Halarm=3; 
         Walert();
         swarm2t=TimeNow;
         swarm2w=w2;
        }
      }
  }

}

В первой строке, в кавычках char phone_no[]=”+123456789012″; – вместо 123456789012 ставим свой номер телефона с кодом страны, на который будут приходить СМС.

Жмем кнопку проверить (над цифрой один в скриншоте выше) – если внизу (под тройкой на скрине) “Компиляция завершена” – то можем прошивать микроконтроллер.

Так, USB-TTL подключен к ARDUINO и компьютеру (как на фото выше) , ставим заряженный аккумулятор в держатель (обычно на новой ардуинке начинает моргать светодиод с частотой раз в секунду).

Теперь прошивка – тренируемся нажимать красную(серебристую) кнопку микроконтроллера – это нужно будет сделать строго в определенный момент!!!
Есть? Жмем кнопку “Вгрузить” (над двоечкой на скриншоте), и внимательно смотрим на строку внизу интерфейса (под тройкой скрина).
Как только надпись “компиляция” сменится “загрузкой” – жмем красную кнопку (ресет) – если все ок – на USB-TTL адаптере радостно заморгают огоньки, а внизу интерфейса надпись “Вгрузили”

Пока мы ждем прихода тестовой СМС на телефон, расскажу как работает программа:

При первом включении система сверяет байты номер 500 и 501 EEPROM если они равны, значит калибровочные данные не записаны, и алгоритм переходит к разделу настройки.
То-же самое происходит, если при включении фоторезистор затенен (пальцем) – активируется режим сброса параметров.

Тензодатчики должны уже быть установлены под ульи, так как мы просто фиксируем начальный уровень нуля и дальше измеряем изменение веса (сейчас просто придут нули, поскольку мы ничего еще не подключали).
На ардуино при этом начнет моргать встроенный светодиод пина 13.
Если сброс не происходит, светодиод загорается на 12 секунд.
После этого отправляется тестовая СМС с сообщением “INITIAL BOOT OK” , процентом заряда батареи и уровнем сигнала сети.

Дальше, у нас работает прерывание по фотодатчику на втором пине (включена подтяжка плюса функцией pullup).
При этом после срабатывания многократно проверяется состояние фоторезистора – для исключения повторных/ложных срабатываний.
Чтобы при каждом включении система не делала сброс, должен быть подключен по крайней мере первый модуль HX711(пины DT-D7, SCK-А0)

Потом снимаются показания тензодатчиков, вычисляется изменение веса с предыдущего срабатывания(первое число в строке после Hive) и от первого включения, проверяется напряжение батареи и эта информация отправляется в виде СМС:

Образец работы системы

Кстати, получили СМС? Поздравляю! Мы на середине пути! Батарею пока можно извлечь из держателя, компьютер нам далее не понадобится.

Приступаем к изготовлению датчиков, для начала коснемся схемы расположения сенсоров:

Расположение сенсоров

Это план улья – вид сверху.

Классически, устанавливаются 4 сенсора по углам (1,2,3,4)

Мы-же мерить будем по-другому. А точнее даже по-третьему. Поскольку по-другому делают ребята из BroodMinder:

BroodMinder

В данной конструкции датчики установлены на позициях 1 и 2, точки 3,4 опираются на брус.
Тогда на сенсоры приходится только половина веса.
Да, такой метод имеет меньшую точность, но все-же трудно представить, чтобы пчелы застроили все рамки “языками” из сот вдоль одной стенки улья.

Так вот, я предлагаю вообще свести датчики в точку 5 – тогда отпадает необходимость в экранировании системы, а при использовании легких ульев и вовсе обходиться одним сенсором.

Итак, на один улей у нас будет устанавливаться два тензодатчика и один модуль HX711 схема распайки следующая:

От платы АЦП до ардуино идет 3 метра 4-жильного телефонного кабеля (в случае модулей веса 2 и 3), первый датчик подключен 10-см “хвостом”, но об этом далее.

В общем, на датчиках веса оставляем “хвосты” по 8см, зачищаем витую пару и все распаиваем как на фото выше.

Прежде, чем начать столярную часть, поставьте воск/парафин в подходящей емкости плавиться на водяную баню.

Теперь берем наш брус и делим на три отрезка по 150мм

Дальше размечаем продольный паз шириной 25 мм, глубиной 7-8мм, с помощью ножовки и стамески убираем лишнее – должен выйти п-образный профиль.

Основы

На самом деле, нам нужна одна Н-образная деталь 1 и две – П-шки, все длинной 15 см.

Зачем Н-ка – не поверите, в ней спрячем Arduino:

чудо враждебной техники

Кроме того, здесь-же крепятся гнезда 6P6C для подключения датчиков 2 и 3.

Воск разогрелся? – окунаем туда наши платы АЦП – это защитит их от влаги/тумана:

Защита АЦП от влаги

Располагаем это все на деревянном основании(необходимо обработать антисептиком от гниения):

Сборка

Ну и наконец, фиксируем датчики саморезами:

Готовый датчик

Далее, паяем все оставшиеся компоненты согласно схеме в шапке и здравому смыслу.

У меня-же вышла следующая конструкция:

Финал

Все, теперь для конечной проверки, ставим датчики по секторам круга, сверху – кусок фанеры, обнуляем контроллер (включаем систему с затененным фотоэлементом).

При этом в течении минуты должна придти тестовая СМС.

Дальше идем набирать воду в 6 – литровую пластиковую бутылку.

Ставим бутылку на фанеру и закрываем фоторезистор пальцем (имитируя закат).

При этом Вам должна придти СМС со значениями веса около 4кг на всех позициях.

Поздравляю! система успешно собрана!

Если теперь заставить систему сработать повторно, то в первой колонке веса получатся нули.

Теперь приведу кратенький мануал по пользованию:

  1. Установить тензодатчики под задние стенки ульев (под передние подставить брус/доску толщиной ~30мм)
  2. Закрепить модуль связи на брус на высоте 2м , с удалением от модулей взвешивания не менее 1м.
    Ориентация солнечной батареи – на юг – желательно по компасу.
  3. Затенить фоторезистор и включить систему тумблером – в течении минуты придет тестовая СМС c текстом “INITIAL BOOT OK”
    Каждый вечер, после заката будет приходить СМС с изменением веса за сутки и с момента запуска.

Но учитывая, что лучьше один раз увидеть, записал коротенькое видео:

Хорошего Вам медосбора!

Электропчеловод Андрей

нужна помощь для поддержки сайта

44 thoughts on “SMS-мониторинг веса трех ульев за 33$”

  1. Используйте библиотеку для HX711 с этого сайта. Если брать с гитхаба то программу надо изменить так:
    Изменил программу:
    // HX711 circuit wiring
    const int scale0_DOUT_PIN = 7;
    const int scale0_SCK_PIN = 14;
    const int scale1_DOUT_PIN = 8;
    const int scale1_SCK_PIN = 14;
    const int scale2_DOUT_PIN = 9;
    const int scale2_SCK_PIN = 14;

    #define SENSORCNT 3
    HX711 *scale[SENSORCNT];

    HX711 scale0;
    HX711 scale1;
    HX711 scale2;

  2. Андрей, добрый день.

    Возможно ли к данной системе прикрутить датчики температуры и влажности ?

    1. Добрый день!
      Если Вы имеете ввиду датчики на каждый улей – то да, возможно, но соединение между блоками взвешивания будут уже 6/8-жильным проводом.

  3. Нашел еще один баг. Измерение уровня заряда батареи измеряется при инициализации и в дальнейшем не измеряется и не изменяется.

    1. Добрый день!
      Спасибо за подсказку, я скоро соберу еще одну версию весов, и исправлю код – не хочется выкладывать непроверенные изменения!

  4. Добрый день
    Собрал схему
    Возникла одна проблемка , которую не могу решить
    Тестовая смс приходит , пишет заряд и уровень сигнала.
    Вторая смс с данными не приходит
    Всем может быт дело?

    1. Добрый день!
      Причин может быть множество.
      Ответил Вам по электронной почте.

      С уважением, Андрей

    2. Добрый день! Вы нашли проблему, я столкнулся с такой же.

  5. Андрей, добрый день!
    Подскажите, тумблер включения у вас между модулем зарядки и модулем связи (я так понимаю для обесточивания всей системы) или между солнечной батареей и модулем зарядки (чтобы отключать зарядку батареи?) ?
    Спасибо!

    1. Обесточивается вся система.

      С уважением, Андрей

      1. Спасибо за ответ.
        Подскажите, пожалуйста, есть еще несколько вопросов:
        1. Собрал систему, прошил плату и сделал тестовый запуск. Пришло 2 смс, как у вас в статье, но только вместо нулей в каждой строке, написано – nan. Это говорит о проблеме, или не обращать внимание и когда уже будут ульи с датчиками, то вес будет нормальный?
        2. не могу найти, где купить гнезда для RJ-12 коннекторов. Подскажите, где вы покупаете? если же не удастся купить, то могу ли я использовать RJ-45, но не для 8 проводов, а для 4х, как у вас в статье, например вставить 4 провода по средине разьема, и так же само 4 провода по средине гнезда?
        3. В теме на точке, вы писали, что воск себя не оправдал как средство от влаги. Посоветуйте, пожалуйста, чем лучше защитить платы HX711 и Arduino от внешней среды? Можно даже с ссылкой на товар в интернете))
        Спасибо!

        1. Добрый день!

          1. Это скорее всего говорит о неправильном подключении тензодатчиков к HX711, либо самих АЦП к Акрдуино.
          Попробуйте отключить платы – должны приходить нули.
          2. Я ищу через интернет – это действительно не самые распространенные коннекторы. Использовать RJ-45 можно.
          3. У некоторых пользователей воск действительно не спасает, обычно для защиты покрывают лаком, я использую акриловый.

          С уважением, Андрей

          1. Добрый день.
            1. NaN пришло в тестовой СМС, когда еще не были подключены ни датчики, ни HX711. Когда подключил первый HX711 к ардуино и проверил систему, то в первой цифре пришло 0.01 (положил телефон на датчики)
            2. Понял, спасибо
            3. А силиконом можно залить?

            Спасибо!

          2. Можно и силиконом, я выбрал воск/парафин ввиду того, что если нужно перепаять, то его можно не удалять.

          3. В общем, все нормально по пункту 1. После подключения датчиков, простановки веса живого, начали приходить цифры.

          4. Рад был помочь!

            С уважением, Андрей.

  6. Появились ещё вопросы. Хочу получать вес в кг и второй цифрой – дельту со вчерашнего дня.

    По коду, я так понимаю, raw02/12/22 содержат данные перед калибровкой.
    Чтобы получить цифру общего веса, необходимо эти данные просто разделить на calibrate0/1/2?
    Вот так? raw02/calibrate0 – это будет чистый вес улья?

    Спасибо.

    1. Для получения полного веса улья нужно сделать сброс системы без установленных под него тензодатчиках.
      Тогда после их установки, система будет показывать изменение от начала работы с учетом полного веса улья и суточную дельту.
      Но все-же на мой взгляд куда полезнее знать не вес улья как такового, а изменение веса от момента запуска системы и за сутки.

      1. Это если внести мои изменения, что я описал? Тогда нужно отпаять все HX платы и запустить со сбросом систему?
        А разве при затененном фотоэлементе не происходит сброс системы, зачем отпаивать?

        Ну,чтобы получить вес мысль у меня правильная? raw02/calibrate0 ?

        1. Для настройки системы отпаивать ничего не надо – это я привел как один из шагов поиска неисправности.
          Начальные параметры в переменных raw00,raw10,raw20 – это не нули а различные значения для каждой конкретной пары АЦП-тензодатчик даже в разгруженном состоянии.
          Сохранение этих значений при запуске – и есть “обнуление”.
          С делением – все верно.

          С уважением, Андрей

      2. Я понял, почему вы выбрали именно такой подход к снятию показаний веса… если снимать точный вес улья, то нужно заниматься калибровкой тензодатчиков постоянно, а та погрешность, которую дает ваш подход – ничтожно мала и ею можно пренебречь, ведь суть показать не точный вес улья, а ЗНАТЬ в каком состоянии находятся пчелосемьи – обильный взяток или поддерживающий или они голодают. А для этих целей именно разницы в весе по сравнению с вчерашним днем – за глаза!

        Спасибо Вам, Андрей, за чудесную наработку!

        1. Снимать вес всего улья кроме всего прочего малоинформативно.
          У кого-то пчелы в толстостенных “Даданах”, у кого-то в полипропиленовых ульях, а кто-то занимается естественным пчеловождением в колодах.
          Но общую идею Вы поняли верно!

  7. Андрей, доброго времени вам.
    Собрав систему и начав ее тестировать, я столкнулся с 2мя проблемами:
    1. При заходе солнца/закрывании фоторезистора полотенцем начинают приходить смс-ки повторно и по много раз. Примерно 1 в минуту.
    Вижу у вас по коду вначале декларации функции SendStat закомментирован кусок кода с английским текстом “ты уверен, что уже sunset?” и с циклом for…
    Раскомментировав этот кусок кода все равно не получил необходимого результата…

    2. Система все никак не хотела сбрасывать начальные показания при старте с затененным фоторезистором(хотя он и мигал несколько раз после этого).
    В коде нашел также закомментированное условие:
    “if (EEPROM.read(500)==EEPROM.read(501) || setZero ) //first boot/reset with hiding photosensor ” – я ее раскомментировал и вроде как сброс данных начал работать

    Все ли правильно я заметил и что мне делать с проблемой постоянных отправок смс при наступлении темноты/полумрака?
    Спасибо!

    1. Добрый день!
      Вы все верно заменили.
      Но даже без этого система корректно работает (перепроверил на тестовой системе).
      Расстояние между модулем связи и микроконтроллером должно быть больше метра.
      Аккумулятор должен быть заряжен.

      С уважением, Андрей

      1. Проблема была не в расстоянии, а в том, что был подключен только 1 HX711, а остальные были не подключены и провода были оголены для их подключения от Ардуино. В общем, когда подключил все HX711 – все стало в норму.
        Спасибо.

  8. Добрый день!
    Почему именно такое решение, с проводами и gsm? Экономика? У меня небольшая стационарная пасека на даче, планирую воспроизвести Ваш опыт в автономном для каждого улья варианте, используя библиотеку mysensors, nrf24 в качестве сенсорной ноды и esp8266 как шлюз. Что думаете?

    1. Приветствую!
      Вариант с NRF24 и ESP8266 хорош для стационарной пасеки с интернетом.
      Решение с проводами – с одной стороны чтобы можно было поднять выше GSM-модуль (для улучшения связи), с другой – проще, дешевле.
      С уважением, Андрей

  9. А можно использовать PL2303HX который уже есть в наличии, или всё-же заказывать CH340?
    И нужно ли тогда ещё искать ноутбук с Win10, ибо есть только с линуксом и старенький с WinXP на котором этот PL2303HX использовался с ds18b20 как термометр.

    1. PL2303HX использовать можно, но под Win10 он не работает.
      Arduino IDE работает и под XP, так что проблем возникнуть не должно.

  10. Так вы использовали 5В ардуино?
    Я не могу прошить боюсь по вашей схема 5В подключил и погорела она…

    1. Добрый день! Ардуино используется 3.3В Для прошивки при подаче 5В на пины самой платы, напряжение на модуль связи не попадает.
      При этом ничего не горит – все чипы Atmega 328 работают на напряжении до 5.5В

      1. ещё один вопрос при подачи питания по вашей схеме нет никакой индикации на ардуино(светодиоди не вы выпаянын). Так и должно быть или где то что то не правильно?

        1. Если на Ардуино ничего не выпаивали – в любом случае должен гореть диод питания.
          Сфотографируйте вашу систему так чтобы четко были видны соединения и пришлите мне на почту letdrive@gmail.com

    1. Добрый день! Это на самом деле и есть моя конструкция на 100% – я дал на тестирование.
      Совместно с автором видео идет доработка и доводка системы.
      Так что причин для волнений нет, но спасибо за внимательность!

  11. Здравствуйте! Пару дней назад увидел на али такие же датчики с HX711 AD и решил собрать подобную систему – а тут Ваш сайт! Я только знакомлюсь с подобными вещами.. разрешите пару вопросов задать?

    1. Можно ли заменить Arduino на ESP8266 / ESP32? У меня стационарная пасека с WiFi 🙂 Или есть платы к Arduino, чтобы к сети цепляться?

    2. Какой емкости у Вас аккумулятор и как долго живёт без солнечной батареи (если есть такая статистика)? Не хочу с ней заморачиваться дополнительно – мне проще раз в X дней снять коробочку и зарядить.

    3. Правильно ли я понял, что на 1 улей в Вашем проекте ставится 6 датчиков и 3 платы HX711 AD?

    4. Фоторезистор у Вас используется для сброса веса и триггера отправки СМС вечером? Классно придумано. Я думал давать моему контроллеру текущее время (по ntp) и время заката/рассвета (от home assistant), но с фоторезистором гораздо надежнее и автономнее выглядит.

    Спасибо!

    1. Добрый день!
      1. Заменить конечно можно, но не факт что будет работать 😉
      Есть модули esp01 (на esp8266), вот они как раз и цепляются к ардуино для связи, но это нужно дописывать программу.
      А вообще существуют проекты непосредственно на ESP32 для умного улья/пасечных весов.

      2. Изначально моя система была без солнечной батареи: https://habr.com/ru/post/444326/
      На аккумуляторе 18650 емкостью 2400 время работы составляло около месяца.

      3. Нет, на один улей ставится 2 датчика, система рассчитана на установку под 3 улья.
      Каждая пара датчиков воспринимает половину веса.

      4. Да, все верно.

  12. Доброго дня
    А ви робите дані ваги на замовлення??

    1. Доброго дня!
      То вже буде на наступний сезон (з цієї зими)
      На три вулики – система “Горинич”, на один – “Міні”
      Зараз йде оптимізація конструкції обох систем.

      З повагою, Андрій

Leave a Reply

Your email address will not be published. Required fields are marked *