ทดลองเชื่อมต่อ Server และใช้ RTC บน Controllino
วันนี้มาทดลองทำการเชื่อมต่อ Controllino เข้ากับ Internet ผ่านทาง Ethernet Port และทำการส่งข้อมูลทุก ๆ 5 นาที หรือทุก 1 หรือ 10 นาที ที่จะต้ังได้ด้วยค่าตัวแปร post_duration
โค้ดชุดนี้ เป็นโค้ดเดิมจากการ Data logger ไปสู่ Server และ MySQL database และเคยเชื่อมต่ออุปกรณ์พื้นฐานต่างๆ เช่น LCD, PZEM power, ต่างๆ เลยยังคงเก็บ การ include library ต่างๆ ไว้เช่นเดิม และดูมันจะรกๆ ซักหน่อย แต่ ไลบลารีที่จำเป็นสำหรับตัวอย่างนี้คือ
#include <SPI.h> และ #include<Controllino.h>
และทำการเอา Controllino ยึดรางลงกล่องกันก่อน ตามรูป พร้อมต่อสาย Lan และ Power Supply 12 Vdc
และขออธิบายเพิ่มเติมจากโค้ดก่อน เฉพาะส่วนที่เกี่ยวข้องกับ controllino
……..
int New_post_time = 0; // กำหนดตัวแปรสำหรับตรวจเวลารอบหใม่
int post_time = 0; // กำหนดตัวแปรสำหรับการบันทึกข้อมูลครั้งก่อน
int Time_check = 0; // กำหนดตัวแปรสำหรับเช็คระยะห่างของเวลา
int post_duration = 5; // กำหนดเวลาการโพสต์ ทุก ๆ 5 นาที
…….
และ ในส่วนของการเช็คเวลาว่าจะทำการบันทึกข้อมูลทุก ๆ 5 นาที
…..
Serial.print(“Minute: “); ส่วนนี้เอาไว้เชคทางพอร์ต serial ว่าเป็นเวลาที่นาทีที่เท่าไหร่
New_post_time = Controllino_GetMinute(); เป็นการกำหนดตัวแปรเวลาใหม่ คือเวลาเป็นนาทีที่ได้จากระบบ RTC ของ controllino
Serial.println(New_post_time); แสดงเวลาค่าใหม่
Time_check = New_post_time – post_time; ตรวจสอบระยะเวลาห่าง
if(Time_check < 0) หากลบกันแล้วน้อยกว่า 0
{
Time_check = New_post_time+60; // บวกเวลาด้วย 60 หากผลลบน้อยกว่า 0 หมายถึงขี้นรอบ ชั่วโมงใหม่
Time_check = Time_check – post_time; //เช็คระยะห่างเวลา
}
Serial.print(“Minute: “); Serial.println(Time_check); //
if (Time_check < post_duration) –> หากยังไม่ครบช่วงเวลาที่กำหนด
{
Serial.println(“No posting….”); –> ก็ไม่ดำเนินการอะไร
delay(1000);
}
else –> หากครบกำหนด 5 นาที
{
Serial.println(“Continue millis()…”); –> ของเก่าลืมลบออก
saveSystemStatusToServer(); –> ทำการเรียกฟังก์ชั่นส่งไป server
post_time = Controllino_GetMinute(); // เวลาเป็นนาที ที่บันทึกข้อมูลครั้งก่อน
}
………..
จากการทดลองรันโค้ด ก็พบว่าระบบจะทำการบันทึกข้อมูลได้อย่างมีเสถียรภาพ ไม่ต้องกังวลเรื่องปัญหา millis() overflow และไม่ต้องติดตั้ง RTC DS3231 จึงเป็นการสร้างงานที่มีเสถียรภาพมากขึ้น
ไว้คราวหน้าเราจะมาทดสอบต่อ Sensor ต่างๆ เข้ากับ Controllino และส่งข้อมูลไปเก็บ และออก แอพมือถือ พร้อมควบคุมการทำงานได้อย่างง่ายดาย
สวัสดีครับ
/*Revision note * Controllino MEGA with Ethernet-Core with Realtime * Version 1.0 Date July 17,2019 * Paipat Samanchuen * */ #include <SPI.h> // must include SPI.h before Controllino.h #include <Controllino.h> #include <SD.h> // Datalogger on Ehthernet Shield 10/8/2018 Paipat #include <Ethernet.h> #include <Wire.h> #include <LCD.h> #include <LiquidCrystal_I2C.h> #include <LiquidCrystal.h> #include "DHT.h" // temperature sensor #include <PZEM004T.h> // Energy meter Through Serial 3 on Mega #include <SoftwareSerial.h> // #include <ArduinoJson.h> #include <NTPClient.h> #include <Arduino.h> #include "RTClib.h" #include <Adafruit_GFX.h> float flowfactor; /// Pin for Manual Auto Raspberry Pi and cooling fan // #define FanPin 25 // #define RaspberryPin 23 #define ManualModePin 38 #define AutoModePin 39 #define DHTPIN 36 #define DHTTYPE DHT11 DHT dht(DHTPIN, DHTTYPE); ////// ////////// Auto Manual Mode //////// int AutoMode = 0; ///// Set time for posting tp server /// int New_post_time = 0; // กำหนดตัวแปรสำหรับตรวจเวลารอบหใม่ int post_time = 0; // กำหนดตัวแปรสำหรับการบันทึกข้อมูลครั้งก่อน int Time_check = 0; // กำหนดตัวแปรสำหรับเช็คระยะห่างของเวลา int post_duration = 5; // กำหนดเวลาการโพสต์ ทุก ๆ 5 นาที ///// /////////// Ethernet Shield ////////////////////////////////////// // Enter a MAC address for your controller below. // Newer Ethernet shields have a MAC address printed on a sticker on the shield byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; // fill in an available IP address on your network here, // for manual configuration: IPAddress ip2(192, 168, 1, 176); // set ip2 192,168,1,176 for Ethernet shield // fill in your Domain Name Server address here: IPAddress myDns(1, 1, 1, 1); // initialize the library instance: // with the IP address and port of the server // that you want to connect to (port 80 is default for HTTP): EthernetClient client; const char* host = "xxxxxxx.com"; /////////////////////// end ethernet shield ///// //// next LCD initial ///// LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7,3,POSITIVE); float LCDDisplayPeriod = 2000; float LastLCDDisplay; float ThisLCDDisplay; //// energy meter setup /// PZEM004T pzem(&Serial3); // Serial Rx3,TX3 on ATMega energy meter IPAddress ip(192,168,1,171); // ip for pzem unit 192,168,1,175 bool pzemrdy = false; /// end PZEM //// /// prepare host url //// String url; // ใช้สำหรับ โปรแกรมส่วนการส่ง int count = 0; int httpPort = 80; float flow55 = 0; //// const int chipSelect = 4; /// control panel condition //// String panelstate = "OFF"; float vHumidity = 0; float vTemperature = 0; float data1=33; float data2=33; float data3=33; float data4=33; float data5=33; float data6=33; float data7=33; float data8=33; float data9=33; float data10=33; float data11=33; float data12=33; float data13=33; float data14=33; float data15=33; float data16=33; float data17=33; float data18=33; float data19=33; float data20=33; /////////////////////////////////////////////////////////////////////////// void setup() { String BCS = "On"; setup_Controllino_RTC(); setup_Display(); setup_PinMode(); setup_SerialCommunication(); setup_NetworkConnection(); setup_DataLogger(); setup_Sensor_Box_Temperature(); } void setup_Controllino_RTC() { Controllino_RTC_init(); // ฟังก์ชั่นการใช้เวลาของ controllino /* set time and date by separate values values to the RTC chip */ /* Day, WeekDay, Month, Year, Hour, Minute, Second); */ Controllino_SetTimeDate(12,4,1,17,15,41,23); /* or use another possibility and define the time and date by strings, e.g. "Nov 15 2018", "11:41:02" */ /* following example uses predefined C macros __DATE__ and __TIME__ which represent compilation time */ Controllino_SetTimeDateStrings(__DATE__, __TIME__); /* set compilation time to the RTC chip */ } //////////////////////////////////////// End SETUP /////////////////////////// void(* resetFunc) (void) = 0; void setup_Display() { lcd.begin(20,4); lcd.setCursor(0,0); lcd.print("IOT by "); lcd.setCursor(0,2); lcd.print("Samong Thailand"); lcd.setCursor(0,3); lcd.print(" Tel. 091-6982616"); delay(1000); } void setup_PinMode() { pinMode(FanPin,OUTPUT); pinMode(RaspberryPin,OUTPUT); // pin 23 pinMode(ManualModePin,INPUT); // ขาวัดโหมด manual pin 38 pinMode(AutoModePin,INPUT); // ขาวัดโหมด Auto pin 39 } void setup_SerialCommunication() { // Open serial communications and wait for port to open: Serial.begin(115200); // mySerial.begin(115200); } void setup_NetworkConnection() { // give the ethernet module time to boot up: delay(1000); // start the Ethernet connection using a fixed IP address and DNS server: Ethernet.begin(mac, ip2, myDns); // print the Ethernet board/shield's IP address: Serial.print("My IP address: "); Serial.println(Ethernet.localIP()); EthernetClient Client; } void setup_DataLogger() { } void setup_Sensor_Box_Temperature() { dht.begin(); } //อ่านสถานะมาเก็บไว้ในตัวแปร void scanSensor_Flowrate() { //ใช้เป็น Interrupt แทน } void scanSensor_Box_Temperature() { } void scanAllSensor() { // scanSensor_Energy(); scanSensor_Box_Temperature(); } //แสดงสถานะการทำงานของระบบ void displayToLCD_Title() { } void displayToLCD_WorkMode() { lcd.clear(); lcd.begin(20,4); lcd.backlight(); lcd.setCursor(0,0); lcd.print("Control Panel check"); lcd.setCursor(0,2); lcd.print("Mode :"); lcd.setCursor(10,2); lcd.setCursor(0,3); lcd.print("Temp 'c :"); lcd.setCursor(10,3); } void displayToLCD_Energy() { } void displayToLCD_All_PumpStatus() { lcd.clear(); lcd.begin(20,4); lcd.backlight(); lcd.setCursor(0,0); lcd.print("Pump Status"); } void displayToLCD_Flowrate() { lcd.clear(); lcd.begin(20,4); lcd.backlight(); lcd.setCursor(0,0); lcd.print("Flow rate L/MIN"); lcd.setCursor(0,3); lcd.print("Total Flow : "); lcd.setCursor(14,3); } void displayToLCD_Flowrate5() { } void displayToLCD_pH_EC_A() { lcd.clear(); lcd.setCursor(0,0); lcd.print("Tamod Station"); lcd.setCursor(0,1); lcd.print(" pH : "); lcd.setCursor(0,2); lcd.print(" EC us/cm : "); lcd.setCursor(0,3); lcd.print(" Temp 'c : "); lcd.setCursor(14,1); lcd.setCursor(14,3); // lcd.print(temperature); } void displayToLCD_pH_EC_B() { } void displayToLCD_Inlet_Outlet() { lcd.clear(); lcd.setCursor(0,0); lcd.print(" inlet outlet"); lcd.setCursor(0,1); lcd.print("pH : "); lcd.setCursor(0,2); lcd.print("EC : "); lcd.setCursor(0,3); lcd.print("Flow : "); lcd.setCursor(9,1); lcd.print("#na"); lcd.setCursor(9,2); lcd.print("#na"); lcd.setCursor(9,3); lcd.print("#na"); } void displayToLCD_TankLevel() { lcd.clear(); lcd.begin(20,4); lcd.backlight(); lcd.setCursor(0,0); lcd.print("Tank Level"); lcd.setCursor(0,1); lcd.print("T#0:"); } void displayToLCD_All_aNodeVoltage() { lcd.clear(); lcd.setCursor(0,0); lcd.print(" Cell Voltage (mV)"); lcd.setCursor(0,1); lcd.print("R1 : "); lcd.setCursor(0,2); lcd.print("R2 : "); lcd.setCursor(0,3); lcd.print("R3 : "); lcd.setCursor(11,1); lcd.print("R4 : "); lcd.setCursor(11,2); lcd.print("R5 : "); } void displayToSerial_Title() { } void displayToSerial_WorkMode() { Serial.println(" Mode check : "); Serial.print("Manual mode switch :"); // Serial.println(ManualModePinValue); Serial.print("Automode switch : "); // Serial.println(AutoModePinValue); Serial.print("Mode Select "); // Serial.println(Modeselect); } void displayToSerial_Energy() { } void displayToSerial_Flowrate() { } void displayToSerial_pH_EC_A() { } void displayToSerial_pH_EC_B() { } void displayToSerial_Inlet_Outlet() { } void displayToSerial_CalculateFlow() { } void displayToSerial_PumpStatus() { } void displayToSerial_TankLevel() { } void displayAllSystemStatus() { displayAllSystemStatusToLCD(); displayAllSystemStatusToSerial(); } void displayAllSystemStatusToLCD() { int timeA = 4000; displayToLCD_Title(); delay(timeA); displayToLCD_Energy(); delay(timeA); displayToLCD_All_PumpStatus(); delay(timeA); displayToLCD_Flowrate(); delay(timeA); displayToLCD_Flowrate5(); delay(timeA); displayToLCD_pH_EC_A(); delay(timeA); // displayToLCD_pH_EC_B(); displayToLCD_Inlet_Outlet(); displayToLCD_TankLevel(); delay(timeA); displayToLCD_All_aNodeVoltage(); delay(timeA); } void displayAllSystemStatusToSerial() { } void saveSystemStatusToServer() { ///// prepare variable of data for upload to server ////// String url = "/iot/api/insertData?device_id=" + String(1)+"&data1=" +String(data1) +"&data2=" + String(data2)+"&data3=" +String(data3)+"&data4=" +String(data4)+"&data5=" +String(data5) +"&data6=" +String(data6)+"&data7=" +String(data7)+"&data8=" +String(data8)+"&data9=" +String(data9) +"&data10=" +String(data10)+"&data11=" +String(data11)+"&data12=" +String(data12)+"&data13=" +String(data13) +"&data14=" +String(data14)+"&data15=" +String(data15)+"&data16=" +String(data16)+"&data17=" +String(data17) +"&data18=" +String(data18)+"&data19=" +String(data19)+"&data20=" +String(data20); /* String url = "/api/weather/insert.php?phinlet=" + String(0) + "&AlarmMessage0=" + String(0); */ Serial.print("Resquesting URL: "); Serial.println(url); delay(1000); // if there's a successful connection: //EthernetClient client; delay(1000); /*if (millis() - lastConnectionTime > postingInterval) { */ if (client.connect(host, 80)) { Serial.println("Data submitting to server ... waiting..."); client.println(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); //client.println("Connection: close"); Serial.println("Data saved completed.."); } else { // if you couldn't make a connection: Serial.println("connection failed 2 "); } while(client.available()) { String line = client.readStringUntil('\r'); Serial.print(line); } /* } */ client.stop(); Serial.println("closing connection"); } /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// void loop() { runSystem(); //ระบบเริ่มทำงาน /// get time Serial.print("Minute: "); New_post_time = Controllino_GetMinute(); Serial.println(New_post_time); Time_check = New_post_time - post_time; if(Time_check < 0) { Time_check = New_post_time+60; // บวกเวลาด้วย 60 หากผลลบน้อยกว่า 0 หมายถึงขี้นรอบ ชั่วโมงใหม่ Time_check = Time_check - post_time; //เช็คระยะห่างเวลา } Serial.print("Minute: "); Serial.println(Time_check); // if (Time_check < post_duration) { Serial.println("No posting...."); delay(1000); //resetFunc(); } else { Serial.println("Continue millis()..."); saveSystemStatusToServer(); post_time = Controllino_GetMinute(); // เวลาเป็นนาที ที่บันทึกข้อมูลครั้งก่อน } } ////////////////////////////////////// end loop ///////// /////////////////////////////////////////////////////////// void runSystem() { } ////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// void initializeAllSensorStatus() { initializeSensorStatus_Energy(); initializeSensorStatus_Flowrate(); initializeSensorStatus_pH(); initializeSensorStatus_EC(); } void initializeSensorStatus_Energy() { } void initializeSensorStatus_Flowrate() { } void initializeSensorStatus_pH() { } void initializeSensorStatus_EC() { } void runMode_Auto() { doModeAuto_Start(); doModeAuto_Operate(); doModeAuto_Complete(); } void doModeAuto_Start() { initializeAllSensorStatus(); } void doModeAuto_Operate() { // readControlCommandFromServer(); scanAllSensor(); displayAllSystemStatus(); // saveSystemStatusToDataLogger(); saveSystemStatusToServer(); // resetAlarmMessage(); } void doModeAuto_Complete() { } void doModeManual_Start() { initializeAllSensorStatus(); } void doModeManual_Operate() { scanAllSensor(); displayAllSystemStatus(); // saveSystemStatusToDataLogger(); saveSystemStatusToServer(); } void doModeManual_Complete() { } void runMode_Manual() { doModeManual_Start(); doModeManual_Operate(); doModeManual_Complete(); } void runMode_Off() { doModeOff_Start(); doModeOff_Operate(); doModeOff_Complete(); } void doModeOff_Start() { initializeAllSensorStatus(); } void doModeOff_Operate() { scanAllSensor(); displayAllSystemStatus(); // saveSystemStatusToDataLogger(); saveSystemStatusToServer(); } void doModeOff_Complete() { displayAllSystemStatus(); } /////////////////////////// end ///////////// void SwitchOnRaspberryPi() { digitalWrite(RaspberryPin,LOW); }