Добрый день, уважаемые форумчане.
Собрал прибор для контроля параметров работы солнечных батарей, аккумуляторов и инвертора.
Три напряжения и три силы тока на аналоговых входах Ардуино-UNO, плюс к тому датчик температуры по OneWire.
Ардуино опрашивает каждый из датчиков 100раз, затем осредняет и результат добавляет в пакет для отправки. Раз в две минуты весь пакет отправляется на сервер через ESP8266.
«На столе» всё работает продолжительно, без замечаний. При подключении к «живым» устройствам, на которых постоянно меняются параметры, Ардуино сразу или через время зависает и может висеть несколько часов, потом сама восстанавливается и продолжает работать. Быстрая перезагрузка не помогает. Длительная перезагрузка помогает, но система снова виснет.
Отключение части датчиков иногда помогает, но системы (чтобы уверенно сказать что какой-то из них перегружает Ардуино) я не увидел.
Подскажите, пожалуйста, правильно ли организована работа моего скетча?
#include <SoftwareSerial.h>
#include <OneWire.h>
#include <DallasTemperature.h>
long nextTime = 100000; // Служебная переменная
//*-- Настройки контроллера
#define SSID "-------" // Название точки доступа
#define PASS "-------" // Пароль
String IP = "--------"; // Адрес сервера
#define esp_bitrate 9600 // Скорость передачи данных между arduino и ESP8266
#define rxpin 10 //RX
#define txpin 11 //TX
#define one_wire_pin 2 // Вход для подключения датчиков тем-ры
#define AnalogIn0 A0 // Аналоговый вход 0 (Напряжение АКБ)
#define AnalogIn1 A1
#define AnalogIn2 A2
#define AnalogIn3 A3
#define AnalogIn4 A4
#define AnalogIn5 A5
//*-- Параметры полученные при регистрации на сайте
String ID = "-------"; // ID (!)
String KEY = "-------"; // Код доступа (!)
long interval = 120000; // Периодичность отправки пакетов на сервер (120 секунд)
//*-- Работа с несколькими датчиками по одной шине
OneWire oneWire(one_wire_pin);
DallasTemperature sensors(&oneWire);
//*-- Software Serial
SoftwareSerial espSerial( rxpin, txpin ); // RX, TX
//*-- GET Information
String GET = "GET /get?cid=" + ID + "&key=" + KEY; // GET request
String HOST = "Host: " + IP + "\r\n\r\n";
void setup() {
Serial.begin(esp_bitrate);
espSerial.begin(esp_bitrate);
sensors.begin(); //Инициализация опроса датчиков температуры DS18B20 (если используются)
sendespSerial("AT");
delay(2000);
if (espSerial.find("OK"))
{
Serial.println("RECEIVED ESP: OK\nData ready to sent!");
connectWiFi();
}
}
void loop() {
//*-- Измерение температуры
sensors.requestTemperatures();
int t1 = round(sensors.getTempCByIndex(0));
delay(2000);
String T1 = String(t1); // turn integer to string
//*-- Измерение напряжения делителем (делается 100 замеров и усредняется)
float Volt32 = 0;
for (int i = 0; i < 100; i++) {
Volt32 = Volt32 + (0.03 * analogRead(AnalogIn5)) / 100; // Пропорция 30,72/4,8В 4.77v
delay(1);
}
String Uakb = String(Volt32);
float VoltPanel = 0;
for (int i = 0; i < 100; i++) {
VoltPanel = VoltPanel + (0.15 * analogRead(AnalogIn4)) / 100; // Пропорция 153,6/4,8В
delay(1);
}
String Upan = String(VoltPanel);
float Volt16 = 0;
for (int i = 0; i < 100; i++) {
Volt16 = Volt16 + (0.015 * analogRead(AnalogIn3)) / 100; // Пропорция 15,36/4,8В
delay(1);
}
String Uakb2 = String(Volt16);
float AmpPanel = 0; // Панели, от 0 до 7 Ампер, измеряется 50-ти амперным датчиком
if(analogRead(AnalogIn2) < 510) {
AmpPanel = 0.01;
delay(1);
}
else {
for (int i = 0; i < 100; i++) {
AmpPanel = AmpPanel + (0.00122 * (analogRead(AnalogIn2) - 510)); // Чувств. датчика 40mV/А
delay(1);
}
}
String TokPanel = String(AmpPanel);
float AmpSKZ = 0; // СКЗ-40, от 0 до 40 Ампер, измеряется 50-ти амперным датчиком
if (analogRead(AnalogIn1) > 510) {
AmpSKZ = 0.01;
delay(1);
}
else {
for (int i = 0; i < 100; i++) { // измерения на датчике тока в диапазоне 0-2.5в, где 2.5в соответствуют 0.00А, а 0в соответствует 50.0А
AmpSKZ = AmpSKZ + (0.00122 * (510 - analogRead(AnalogIn1))); // Чувств. датчика 40mV/А
delay(1);
}
}
String TokSKZ = String(AmpSKZ);
float AmpDD = 0; // DualDSP, от 0 до 100 Ампер, измеряется 100 амперным датчиком
// возможны отрицательные значения (при зарядке батарей от сети)
for (int i = 0; i < 100; i++) {
AmpDD = AmpDD + (0.0024414 * (analogRead(AnalogIn0) - 510)); // Чувств. датчика 20mV/А
delay(1);
}
String TokDD = String(AmpDD);
if ( millis() - nextTime > (interval - 4215) ) {
// Отправляем пакет на сервер,
update_param(T1, Uakb, Upan, Uakb2, TokPanel, TokSKZ, TokDD);
nextTime = millis();
}
}
//*-- Функции --*//
//*--Функция отправки в порт ESP и терминал
void sendespSerial(String cmd) {
Serial.print("SEND: ");
Serial.println(cmd);
espSerial.println(cmd);
}
//*-- Соединение с точкой доступа
boolean connectWiFi() {
espSerial.println("AT+CWMODE=1"); // Режим работы "клиент"
delay(2000);
String cmd = "AT+CWJAP=\""; // Подключение к точке доступа
cmd += SSID;
cmd += "\",\"";
cmd += PASS;
cmd += "\"";
sendespSerial(cmd);
delay(5000);
if (espSerial.find("OK"))
{
Serial.println("Connect: OK");
return true;
}
else
{
Serial.println("Connect: Error");
return false;
}
cmd = "AT+CIPMUX=0"; // Режим одиночного соединения
sendespSerial( cmd );
if ( espSerial.find( "Error") )
{
Serial.print( "RECEIVED: Error" );
return false;
}
}
//*--- Отправка данных на сервер, если есть параметры, так же дописать через запятую с указанием типа, например: String T3
// void update_param( String T1, String Uakb, String Upan, String Uakb2, String TokPanel, String TokSKZ, String TokDD) {
void update_param( String T1, String Uakb, String Upan, String Uakb2, String TokPanel, String TokSKZ, String TokDD) {
String cmd = "AT+CIPSTART=\"TCP\",\""; // Setup TCP connection
cmd += IP;
cmd += "\",80";
sendespSerial(cmd);
delay(1000);
if ( espSerial.find( "Error" ) )
{
Serial.print( "RECEIVED: Error\nExit1" );
connectWiFi();
return;
}
// Отправка строки на сервер
// cmd = GET + "&p1=" + T1 + "&p2=" + Uakb + "&p3=" + Upan+ "&p4=" + Uakb2 + "&p5=" + TokPanel + "&p6=" + TokSKZ + "&p7=" + TokDD ;
cmd = GET + "&p1=" + T1 + "&p2=" + Uakb + "&p3=" + Upan+ "&p4=" + Uakb2 + "&p5=" + TokPanel + "&p6=" + TokSKZ + "&p7=" + TokDD;
cmd += " HTTP/1.1\r\n" + HOST;
espSerial.print( "AT+CIPSEND=" );
espSerial.println( cmd.length() );
if (espSerial.find( ">" ) )
{
Serial.print(">");
Serial.print(cmd);
espSerial.print(cmd);
delay(30);
}
else
{
sendespSerial( "AT+CIPCLOSE" ); //close TCP connection
}
if ( espSerial.find("OK") )
{
Serial.println( "RECEIVED: OK" );
}
else
{
Serial.println( "RECEIVED: Error\nExit2" );
connectWiFi();
}
}
Вставьте для начала код нормально (в общих есть тема) и дайте схему.
Спасибо. Сейчас разберусь, сделаю.
Со схемой сложнее. Не подумал, что она нужна.
Три делителя напряжений, три датчика тока ACS758, обвязка соединения с платой Wi-Fi
Сегодня уже ночь. Завтра нарисую и выложу.
Подскажите, пожалуйста, правильно ли организована работа моего скетча?
В целом нормально, но лучше избавиться от таких конструкций:
Volt32 = Volt32 + (0.03 * analogRead(AnalogIn5)) / 100;
Лучше вычичсления делать в целых числах, а форматировать при выводе.
Так же фукция update_param принимает кучу стрингов. Лучше передать в нее лонги, а их форматирванием заняться в самой фунции.
Может просто не хватать памяти....
Спасибо. Понял. Буду исправлять.
Схема нарисовалась вот такая.
Три датчика тока, три делителя напряжения (на 16в, на 32в и на 150в)
Вышло так, что "масса" общая для всех приборов.
В DC-DC конверторе "минус" входа и выхода общий. На контролере солнечных батарей - тоже общий.
На инверторе - не знаю.
Для экономии я собрал вместе и посадил на один конденсатор питание датчиков тока ACS758.
"на столе" всё работает, но какой частоты токи используют приборы и может ли это мешать Ардуино - даже предположить не могу.
Как считаете, не нужно ли где-то разделить всё это хозяйство по питанию?