Advertisement
tpaper

H0T pump

May 15th, 2018
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.09 KB | None | 0 0
  1. #include <stdint.h>
  2. #include <ESP8266WiFi.h>
  3. #include <WiFiUdp.h>
  4. #include <Time.h>
  5. #include <EEPROM.h>
  6. extern "C" {
  7. #include "user_interface.h"
  8. }
  9.  
  10. //PINs definition
  11. #define WOK_PIN 14  //WiFi status led
  12. #define RLY_PIN  4  //Relay+led (Pompa ricircolo)
  13. #define LED_PIN  5  //Led       (Pompa scarico)
  14. #define MOD_PIN  0  //Mode switch (0 -> fw update/debug, 1 -> normal operation)
  15.  
  16. #define DEBUG_PUMP_PERIOD_SEC 10 //How long pump stays on (seconds)
  17.  
  18. #define TIMEZONE 1  //Timezone (Rome UTC+1)
  19. #define TIME_SYNC_INTERVAL 24*60*60 //Interval between two internet time sync (seconds)
  20. #define SHORT_TIME_SYNC_INTERVAL 5*60
  21. #define MAX_SYNC_TRIES 5 //Maximum time sync tries before give up
  22.  
  23. //UDP send/receive settings
  24. WiFiUDP       udp_handle;
  25. WiFiUDP       udp_log_handle;
  26. WiFiUDP       udp_time_handle;
  27. unsigned int  udp_port = 4200;
  28. char          udp_buffer[255];
  29. int           udp_size;
  30. int           udp_len;
  31.  
  32. unsigned int  udp_log_port = 4201;
  33. unsigned int  udp_time_port = 4202;
  34. IPAddress     udp_timeserver_ip(192,168,1,101);
  35. IPAddress     udp_logserver_ip(192,168,1,101);
  36.  
  37. //UDP commands/reply
  38. char command_start[]  = "START";
  39. char command_stop[]   = "STOP";
  40. char command_toggle[] = "TOGGLE";
  41. char command_status[] = "STATUS";
  42. char command_debug[]  = "DEBUG";
  43. char reply_roger[]    = "ROGER";
  44. char reply_err[]      = "ERR";
  45. char period_set_char  = 0x80;   //Command to set pump period duration
  46. char count_reset_char = 0x81;   //Command to reset total pump count
  47. char valid_udp_time   = 0x82;
  48. uint8_t reply_roger_len = 5;
  49.  
  50. uint8_t PUMP_PERIOD_SEC; //How long pump stays on (seconds) 0-255
  51. uint16_t PUMP_COUNT;     //Total count of pump use
  52.  
  53. //Timer handle
  54. os_timer_t tmr_handle;
  55.  
  56. //Timestamps
  57. uint32_t tmst       = 0; //Internal timestamp
  58. uint32_t stop_tmst  = 0; //When stop the pump
  59. uint32_t boot_tmst  = 0; //Last boot timestamp
  60. uint32_t last_sync_tmst  = 0; //Last time sync
  61. uint32_t next_sync_tmst  = 0; //Next time sync
  62. uint32_t last_hot_pump_tmst  = 0; //Last time hot pump started
  63.  
  64. int flag_every_sec_routine = 0;
  65.  
  66. void every_sec(void *pArg) {  //Increments the timestamp every second
  67.   tmst++;
  68.   flag_every_sec_routine = 1;
  69. }
  70.  
  71. void every_sec_routine(){
  72.   if(tmst>next_sync_tmst) sync_time();  
  73.   flag_every_sec_routine = 0;
  74. }
  75.  
  76. void setup() {
  77.   //IO settings
  78.   pinMode(WOK_PIN,OUTPUT);
  79.   pinMode(RLY_PIN,OUTPUT);
  80.   pinMode(LED_PIN,OUTPUT);
  81.   pinMode(MOD_PIN,INPUT);
  82.  
  83.   //Serial settings and welcome message
  84.   Serial.begin(115200);
  85.   Serial.println("\nBooted into normal mode");
  86.  
  87.   //WiFi connection
  88.   Serial.println("Started V2...");
  89.   Serial.print("Connecting... ");
  90.   WiFi.enableAP(0);
  91.   WiFi.hostname("ESP_Cantina");
  92.  
  93.   IPAddress ip(192, 168, 1, 100);
  94.   IPAddress gateway(192, 168, 1, 1); // set gateway to match your network
  95.   IPAddress subnet(255, 255, 255, 0); // set subnet mask to match your
  96.   WiFi.config(ip, gateway, subnet);
  97.  
  98.   WiFi.begin("EIR-0366", "69449390076557713985");
  99.   while(WiFi.status() != WL_CONNECTED) {digitalWrite(WOK_PIN,!digitalRead(WOK_PIN)); delay(200);}
  100.   Serial.print("Connected: IP address: ");
  101.   Serial.println(WiFi.localIP());
  102.  
  103.   //EEprom init
  104.   EEPROM.begin(512);    //512 byte eeprom
  105.   load_EEPROM_conf();
  106.  
  107.   udp_time_handle.begin(udp_time_port);
  108.   sync_time();
  109.   boot_tmst = tmst;
  110.  
  111.   //Set the timer for increment the timstamp every second
  112.   os_timer_setfn(&tmr_handle, every_sec, NULL);
  113.   os_timer_arm(&tmr_handle, 1000, true);
  114.  
  115.   //Start listening for UDP packets
  116.   udp_handle.begin(udp_port);
  117. }
  118.  
  119. void loop() {
  120.   while(1){ //Main loop
  121.     ESP.wdtFeed();  //Reset watchdog
  122.     if(flag_every_sec_routine) every_sec_routine();
  123.    
  124.     if(WiFi.status() == WL_CONNECTED) digitalWrite(WOK_PIN,HIGH); else digitalWrite(WOK_PIN, LOW);  //WiFi led ok
  125.    
  126.     //Controlla se ha ricevuto pacchetti UDP
  127.     udp_size = udp_handle.parsePacket();
  128.     if(udp_size) udp_received();
  129.  
  130.     //Ferma la pompa quando necessario
  131.     if(digitalRead(RLY_PIN) && (tmst > stop_tmst)) digitalWrite(RLY_PIN,LOW);
  132.    
  133.     yield();
  134.   }
  135. }
  136.  
  137. void udp_received() { //Routine che viene chiamata in caso di ricezione di pacchetti
  138.   delay(10);
  139.   udp_len = udp_handle.read(udp_buffer,255);
  140.   if(udp_len>0){
  141.     udp_buffer[udp_len] = '\0'; //Inserisco il terminatore alla fine
  142.     //Parsing del comando
  143.     if(!strcmp(udp_buffer,command_start)) {
  144.       if((!digitalRead(RLY_PIN)) && (!debug())) {
  145.         uint16_t tmp = PUMP_COUNT+1;
  146.         while(PUMP_COUNT != tmp) {
  147.           set_EEPROM_count(tmp);
  148.           delay(10);
  149.           load_EEPROM_conf();
  150.         }
  151.         sprintf(udp_buffer,"%lu\n",tmst);
  152.         udp_log_handle.beginPacket(udp_logserver_ip,udp_log_port);
  153.         udp_log_handle.write(udp_buffer);
  154.         udp_log_handle.endPacket();        
  155.       }
  156.       digitalWrite(RLY_PIN,HIGH);
  157.       if(!debug()) last_hot_pump_tmst = tmst;
  158.       strcpy(udp_buffer,reply_roger);
  159.       if(debug()){
  160.         stop_tmst = tmst + DEBUG_PUMP_PERIOD_SEC;
  161.         udp_buffer[reply_roger_len] = DEBUG_PUMP_PERIOD_SEC;
  162.       } else {
  163.         stop_tmst = tmst + PUMP_PERIOD_SEC;
  164.         udp_buffer[reply_roger_len] = PUMP_PERIOD_SEC;
  165.       }
  166.       udp_buffer[reply_roger_len+1] = '\0';
  167.       udp_send(udp_buffer,udp_handle.remoteIP());
  168.     } else if (!strcmp(udp_buffer,command_stop)) {
  169.       digitalWrite(RLY_PIN,LOW);
  170.       udp_send(reply_roger,udp_handle.remoteIP());
  171.     } else if (!strcmp(udp_buffer,command_debug)) {
  172.       //Format: utc_timestamp;local_timestamp;last_boot;last_sync;hot_water_pump_status
  173.       Serial.print("Received DEBUG command from ");
  174.       Serial.println(udp_handle.remoteIP());
  175.       sprintf(udp_buffer,"%lu;%lu;%lu;%lu;%d;%lu;%u;%u",tmst,local_time(tmst),local_time(boot_tmst),local_time(last_sync_tmst),digitalRead(RLY_PIN),local_time(last_hot_pump_tmst),PUMP_PERIOD_SEC,PUMP_COUNT);
  176.       udp_send(udp_buffer,udp_handle.remoteIP());
  177.     } else if (udp_buffer[0] == period_set_char) {
  178.       uint8_t tmp;
  179.       tmp = udp_buffer[1];
  180.       while(PUMP_PERIOD_SEC != tmp) {
  181.         set_EEPROM_period(tmp);
  182.         delay(10);
  183.         load_EEPROM_conf();
  184.       }
  185.       udp_send(reply_roger,udp_handle.remoteIP());
  186.     } else if (udp_buffer[0] == count_reset_char) {
  187.       uint16_t tmp;
  188.       tmp = (udp_buffer[1]<<8) + udp_buffer[2];
  189.       while(PUMP_COUNT != tmp) {
  190.         set_EEPROM_count(tmp);
  191.         delay(10);
  192.         load_EEPROM_conf();
  193.       }
  194.       udp_send(reply_roger,udp_handle.remoteIP());
  195.     } else {
  196.       udp_send(reply_err,udp_handle.remoteIP());
  197.     }
  198.   }
  199. }
  200.  
  201. void udp_send(char *message, IPAddress ip){
  202.   udp_handle.beginPacket(ip,udp_port);
  203.   udp_handle.write(message);
  204.   udp_handle.endPacket();
  205. }
  206.  
  207. void sync_time(){                         //sync system time with internet
  208.   uint16_t l,i = millis();
  209.   bool timeset = false;
  210.   char str_buff[255];
  211.   Serial.println("Requested time sync");
  212.   udp_time_handle.beginPacket(udp_timeserver_ip,udp_time_port);
  213.   udp_time_handle.write("TMRQ");
  214.   udp_time_handle.endPacket();
  215.  
  216.   while(((millis()-i) < 5000) && (timeset == false)){
  217.     l = udp_time_handle.parsePacket();
  218.     if(l){
  219.       udp_len = udp_time_handle.read(udp_buffer,16);
  220.       if(udp_len > 0){
  221.         //sprintf(str_buff,"\nRECV: %x | %x %x %x %x | %x\n",udp_buffer[0],udp_buffer[1],udp_buffer[2],udp_buffer[3],udp_buffer[4],udp_buffer[5]);
  222.         //Serial.printf(str_buff);
  223.         if(udp_buffer[0] == valid_udp_time){
  224.           tmst = udp_buffer[1]<<24 | udp_buffer[2]<<16 | udp_buffer[3]<<8 | udp_buffer[4];
  225.           Serial.println("Time set!");
  226.           timeset=true;
  227.           last_sync_tmst = tmst;
  228.           next_sync_tmst = tmst + TIME_SYNC_INTERVAL;
  229.           if(boot_tmst < 10000){
  230.             boot_tmst = tmst;
  231.           }
  232.         }
  233.       }
  234.     }
  235.     yield();
  236.   }
  237.   if(!timeset) {
  238.     next_sync_tmst = tmst + SHORT_TIME_SYNC_INTERVAL;
  239.     Serial.println("Giveup :(");
  240.   }
  241. }
  242.  
  243. uint32_t local_time(uint32_t UTC) {           //give UTC time gives the local time
  244.   return UTC + (TIMEZONE + is_DST(UTC))*3600;
  245. }
  246.  
  247. int is_DST(uint32_t t){                       //return 1 if DST is in use in t timestamp, 0 otherwise
  248.   tmElements_t DST_start, DST_end;
  249.   uint32_t DST_start_t, DST_end_t;
  250.    
  251.   DST_start.Second = 0;
  252.   DST_start.Minute = 0;
  253.   DST_start.Hour = 1;
  254.   DST_start.Year = year(t) - 1970;
  255.  
  256.   DST_end = DST_start;
  257.   DST_start.Month = 3; DST_end.Month = 10;
  258.  
  259.   DST_start.Day = (31-((((5*year(t))/4)+4)%7));
  260.   DST_end.Day =  (31-((((5*year(t))/4)+1)%7));
  261.  
  262.   DST_start_t = (uint32_t) makeTime(DST_start);
  263.   DST_end_t = (uint32_t) makeTime(DST_end);
  264.  
  265.   if( (t > DST_start_t) && (t < DST_end_t) ) return 1;
  266.   return 0;
  267. }
  268.  
  269. //EEPROM fun
  270. /*
  271.  * ADDR   DESC
  272.  *
  273.  * 0      Pump interval (seconds)
  274.  * 1      Pump count (msb)
  275.  * 2      Pump count (lsb)
  276.  */
  277.  
  278. void load_EEPROM_conf() {
  279.   PUMP_PERIOD_SEC = EEPROM.read(0);
  280.   PUMP_COUNT = (EEPROM.read(1))<<8 | EEPROM.read(2);
  281. }
  282.  
  283. void set_EEPROM_count(uint16_t count) {
  284.   EEPROM.write(2, count & 0xFF);
  285.   EEPROM.write(1, count>>8);
  286.   EEPROM.commit();
  287. }
  288.  
  289. void set_EEPROM_period(uint8_t period) {
  290.   EEPROM.write(0,period);
  291.   EEPROM.commit();
  292. }
  293.  
  294. boolean debug() {
  295.   return !digitalRead(MOD_PIN);
  296. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement