Зависание Arduino из-за кода
- Войдите на сайт для отправки комментариев
Ср, 04/02/2015 - 19:21
Здравствуйте товарищи. Не могли бы Вы объянить мне что не так? Залив скетч из примеров ардуино работает как надо, но как только я заливаю данный скетч ардуино зависает, а проявляется это в следующем, часы могут просто залипать и выдать значения секунд или минут с запозданием. Так же после значения температуры появляются фантомные нули и так же показывает иногда -127 градусов. Вот скетч:
#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h>
#define DS1307_I2C_ADDRESS 0x68
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}
void setDateDs1307(byte second, // 0-59
byte minute, // 0-59
byte hour) // 0-99
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.write(decToBcd(second));
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.endTransmission();
}
void getDateDs1307(byte *second,
byte *minute,
byte *hour)
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 3);
*second = bcdToDec(Wire.read());
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read());
}
LiquidCrystal_I2C lcd(0x27,16,2);
OneWire oneWire(10);
DallasTemperature sensors(&oneWire);
DeviceAddress tempDeviceAddress;
float temp1=0;
int setTmp=24;
long previousMillis1 = 0;
long interval1 = 1000;
char incomingByte;
int On_Time=0;
int Off_Time=0;
int Curent_Time=0;
int Relay_1 = 2; // R1 - Свет
int Relay_2 = 3; // R2 - Вентиляция
int Relay_3 = 4; // R3 -
int Relay_4 = 5; // R4 -
void setup(){
Wire.begin();
Serial.begin(9600);
lcd.init();
lcd.backlight();
Serial.println("Version: PC-Box");
Serial.println("Controller: ON \n");
delay(1000);
lcd.clear();
sensors.begin();
sensors.getAddress(tempDeviceAddress, 0);
sensors.setResolution(12);
pinMode(Relay_1, OUTPUT);
pinMode(Relay_2, OUTPUT);
pinMode(Relay_3, OUTPUT);
pinMode(Relay_4, OUTPUT);
digitalWrite(Relay_1, LOW);
digitalWrite(Relay_2, LOW);
digitalWrite(Relay_3, HIGH);
digitalWrite(Relay_4, HIGH);
}
void loop(){
byte second, minute, hour;
getDateDs1307(&second, &minute, &hour);
lcd.setCursor(0,0);
if (hour < 10) {
lcd.print ("0");
lcd.print (hour);
}
else {
lcd.print (hour);
}
lcd.print(":");
if (minute < 10) {
lcd.print ("0");
lcd.print (minute);
}
else {
lcd.print (minute);
}
lcd.print(":");
if (second < 10) {
lcd.print ("0");
lcd.print (second);
}
else {
lcd.print (second);
}
//************************************************************
On_Time=(6*60+01)-1;
Off_Time=(23*60+59)-1;
Curent_Time=hour*60+minute;
if(On_Time < Off_Time)
{
if (Curent_Time >= On_Time && Curent_Time <= Off_Time)
{
digitalWrite(Relay_1, LOW);
lcd.setCursor(9, 0);
lcd.print("R1+");
}
else
{
digitalWrite(Relay_1, HIGH);
lcd.setCursor(9, 0);
lcd.print("R1-");
}
}
else
{
if ((Curent_Time >= On_Time && Curent_Time <= 2820)||(Curent_Time >= 0 && Curent_Time <= Off_Time))
{
digitalWrite(Relay_1, LOW);
lcd.setCursor(9, 0);
lcd.print("R1+");
}
else
{
digitalWrite(Relay_1, HIGH);
lcd.setCursor(9, 0);
lcd.print("R1-");
}
}
//************************************************************
unsigned long currentMillis1 = millis();
if(currentMillis1 - previousMillis1 > interval1)
{
previousMillis1 = currentMillis1;
sensors.setWaitForConversion(false);
sensors.requestTemperatures();
sensors.setWaitForConversion(true);
sensors.getAddress(tempDeviceAddress, 0);
temp1=sensors.getTempC(tempDeviceAddress);
lcd.setCursor(0, 1);
lcd.print(temp1);
lcd.setCursor(6, 1);
lcd.print("*C");
}
if (temp1>=setTmp)
{
digitalWrite(Relay_2, LOW);
lcd.setCursor(13, 0);
lcd.print("R2+");
}
if (temp1<setTmp)
{
digitalWrite(Relay_2, HIGH);
lcd.setCursor(13, 0);
lcd.print("R2-");
}
//************************************************************
if (Serial.available() > 0)
{
incomingByte = Serial.read()-48;
if(incomingByte == 1)
{
Serial.print("Temp: ");
Serial.print(temp1);
Serial.println(" *C");
Serial.print("Time: ");
if (hour < 10) {
Serial.print ("0");
Serial.print (hour);
}
else
{
Serial.print(hour);
}
Serial.print(":");
if (minute < 10)
{
Serial.print ("0");
Serial.print (minute);
}
else
{
Serial.print (minute);
}
Serial.print(":");
if (second < 10)
{
Serial.print ("0");
Serial.println (second);
}
else
{
Serial.println (second);
}
Serial.print(F("Core: "));
Serial.print(GetTemp(),1);
Serial.println(" *C");
}
if(incomingByte == 3)
{
int Val = !digitalRead(Relay_3);
digitalWrite(Relay_3, Val);
lcd.setCursor(9, 1);
lcd.print( Val ? "R3-" : "R3+" );
Serial.println( Val ? "Relay_3 OFF" : "Relay_3 ON" );
}
if(incomingByte == 4)
{
int Val = !digitalRead(Relay_4);
digitalWrite(Relay_4, Val);
lcd.setCursor(13, 1);
lcd.print( Val ? "R4-" : "R4+" );
Serial.println( Val ? "Relay_4 OFF" : "Relay_4 ON" );
}
}
}
//************************************************************
double GetTemp(void)
{
unsigned int wADC;
double t;
// Set the internal reference and mux.
ADMUX = (_BV(REFS1) | _BV(REFS0) | _BV(MUX3));
ADCSRA |= _BV(ADEN); // enable the ADC
delay(20); // wait for voltages to become stable.
ADCSRA |= _BV(ADSC); // Start the ADC
// Detect end-of-conversion
while (bit_is_set(ADCSRA,ADSC));
// Reading register "ADCW" takes care of how to read ADCL and ADCH.
wADC = ADCW;
// The offset of 324.31 could be wrong. It is just an indication.
t = (wADC - 324.31 ) / 1.22;
// The returned temperature is in degrees Celcius.
return (t);
}
За ранее Спасибо всем откликнувшимся.
шины I2C резисторами 4,7 kOm к +5 V подтянули ? адреса пользователей I2C не конфликтуют ?
библиотеки строки 1 и 2 - совместимы ? длинные коды - сворачивать надо, хороший тон, схему подключения надо
а по отдельности пробовали все узлы погонять ?
Да нонечно, DS18b20 на 10к питание 5v, а lcd на 4,7к. Библиотека вроде бы тоже норм, на них греха не подать. А вот на счет длинных кодов не понял, всмысле сворачивать? По отдельности все работает на ок) даже придратся не могу. Подключаю так, по i2c первым идут часы ds1307 к ним через мост предусмотренный на плате подключен и сам lcd.
Часы:
http://ru.aliexpress.com/item/1-pcs-I2C-RTC-DS1307-AT24C32-Real-Time-Clo...
Ардуино:
http://ru.aliexpress.com/item/Free-shipping-high-quality-UNO-R3-MEGA328P...
DS18b20:
http://ru.aliexpress.com/item/Stainless-steel-package-Waterproof-DS18b20...
У меня практики то на ардуино да и вообще програмирования пару недель :(
Ну во первых, если часы прилепили на lcd резисторы уже не нужны. И попробуйте не через гребенку часов а параллельно их включить. Код сворачивать - там галочка есть когда вставляете, чтобы вашу портянку по экрану не гонять.
Спасибо, на счет портянки понял :) буду теперь знать. Подключил паралельно, работает без зависаний, значит что то с часами не то, а вот почему фантомные нули появляются не пойму.
Спасибо, на счет портянки понял :) буду теперь знать. Подключил паралельно, работает без зависаний, значит что то с часами не то, а вот почему фантомные нули появляются не пойму.
Скорее какие то паразитные наводки при сквозном проходе.
Не понял на счет наводок и сквозном проходе) разьясните на пальцах)
Привет у меня не много опыта что бы проанализировать код, и что то подсказать, но мой совет в цикле
void loop(){ }Вставте больше выводов в терминал ( значения переменной, коментарий действий).
Очень облегчат диагностику.
Ну и для нас, будет больше информации.
Не понял на счет наводок и сквозном проходе) разьясните на пальцах)
Если как вы сказали, что после отключения линий со второй гребенки часов и подключения их просто параллельно проблема исчезла, значит что то происходит во время прохождения сигналов по плате часов.
Не понял на счет наводок и сквозном проходе) разьясните на пальцах)
1 пин источник и 7 пинов приёмников , подключать надо семью проводами 1 - 2 , 1 - 3 , 1 - 4 ........... ,
а не - 1 - 2 - 3 - 4 -5 - 6 - 7 - 8..... так на крайнем пине будет сигнал от 1 и мусор-помехи от других пинов
Я понял о чем Вы) с помехами я уже разобрался) но только что ds18b20 показывает -127 не погу понять. Если надо я могу припаять поключения к дуино без ножек, это поможет?
сделайте для него отдельный код, проверьте отдельно
Я дико извеняюсь, что нет описания :( но код приметивен и думаю тут особо и разбиратся не с чем :) А зачем больше выводов в терминал?
в стандартном примере даласа все работает нормально.
Я понял о чем Вы) с помехами я уже разобрался) но только что ds18b20 показывает -127 не погу понять. Если надо я могу припаять поключения к дуино без ножек, это поможет?
Потеребите еще раз все контакты на DS-ке и резисторе. А он что то другое показывал кроме этого?
Я дико извеняюсь, что нет описания :( но код приметивен и думаю тут особо и разбиратся не с чем :) А зачем больше выводов в терминал?
имитация пошагового режима :)
да, саму темпиратуру. Он работать может и минут 20, а бывает что тупо прыгает то привильно показыает то -127.
-127 означает нет контакта...если я не ошибаюсь,вы подтянули ножку питания датчика к ножке данных резистором 10к(ваш пост #2)..это много,по даташиту 4.7к,а в реальности обычно меньше,от 1.2к ну и до 4.7к...вобщем мой совет,попробуйте опытным путем уменьшите сопротивление подтяжки датчика...
Заменил DS18b20 на другой, проблема изчезла, думаю что то с нам. но не пойму почему он работал отдельно :( сказывается опыт :(
вот это как раз симптомы не удачного сопротивления....я,кстати,у себя сделал програмную фильтрацию от значения -127,просто у меня на шине много датчиков и сама шина длинная,наводки,то се,полностью без ошибок не получается получать температуру с датчиков..в скетче отсеиваю ложные значения и все дела..
Понял, начну с 1,2к на подтяжку. Просто где я взял кусок кода на 18b20 было указано что нужно подключать на 10к .
И еще наводящий вопрос, у вас в коде есть релюшки, они физически сейчас щелкают?
У меня конечно же не шлейф) а один) но все же, не могли бы Вы описать как вы отсеиваете ложные сигналы, что бы это повторить у себя, кто значет быть может поможет.
Да, они шелкают как надо, как по времени таки по темпиратуре. Знаю что в коде все может на первый взгляд выглядет что не правильно написано, но я Вас уверяю что се работает исправно)
лучше начинать с 4,7 и двигаться к 1,2 :)
Да, они шелкают как надо, как по времени таки по темпиратуре. Знаю что в коде все может на первый взгляд выглядет что не правильно написано, но я Вас уверяю что се работает исправно)
В зависимости как они запитаны, тоже могут давать помеху на датчик, фантомные нули на lcd и прочее.
Посадил на припой все провода ds18b20 и работает на ура :))) Резюк поставил на 4,7к. Осталовь все установить в корпус сея устройства http://ru.aliexpress.com/item/12V-2A-24W-LED-Strip-Light-Switch-Power-Su...
и подключить нагрузку :) Чем уже и занят :) Всем ОГРОМНОЕ Спасибо за советы, без Вас не куда :)
ну вот вам огрызок с моего скетча
есть два массива:temp-окончательный,к которому мы обращаемся во время формирования веб-странички(а там я не хочу наблюдать невнятные значения=)) и inttemp-промежуточный массив...алгоритм прост:по таймеру(раз в минуту к примеру)вызывается функция опроса датчиков и полученные значения заносятся в inttemp,а далее циклом я проверяю их на ошибки и если все ок,то переношу корректную температуру в массив temp..все чем я рискую,если была ошибка,то просто отображаемая температура с датчика который в данный опрос дал ошибку,будет устаревшая на минуту=))
float inttemp[9] = {0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00}; // массив для промежуточных температур float temp[9] = {0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00}; // массив для текущих корректных температур for(int i = 0; i < 9; i++){ // фильтруем значения в массиве,если значения корректные,то заносим их окончательно в массив температур if((inttemp[i] != -127) && (inttemp[i] != 0.00) && (inttemp[i] != 85.00)){ temp[i] = inttemp[i]; } }Опытным путем я понял что не стоит питание реле питать от ардуино) ибо грелся ужасно сильно плата. После этого я отвел отдельное питание для них)
лучше начинать с 4,7 и двигаться к 1,2 :)
да,верное замечание=)
а зачем в массив ? чё не налету проверять ? ошибка - повторить опрос... а помнить только предзначение
Спасибо :) за фильтр. Это чудо мне пригодится для следующего проектра где будут более 6 датчиков :)
делал и на лету,но повторить запрос,соответственно время на конвертацию,если глюкнуло пару датчиков,запинка будет ощутима...я посчитал,что в моих условия мне можно этим пренебречь..пока так,а там как подойду к стадии оптимизации кода,может и изменю=)
согласен.... только зачем массив ? запоминать одно крайнее верное - для отката, если текущее ошибочное :) ( без переопроса глюкнувшего датчика )
у меня над этим кодом прежде чем занести значение в inttemp я провожу проверку на валидность встроенной функцией sensors.validAddress и тд...так как шин датчиков у меня три,да еще и не в окончательном варианте все(адреса датчиков еще перекидую порой с шины на шину),просто одним циклом это все не обработать,а так код будет из многа строк и букаф=)я вашу идею понял,сводится к тому,что массив inttemp можно исключить и сэкономить тем самым 40 байт оперативки...чуть позжее займусь этим=)
:) 2 массива по 9 значений по 4 байта = 72
Массив temp должен быть полюбому,ведь веб-страничка может дергаться несколько раз в минуту,зачем мне опрашивать каждый раз датчики и проводить сотню фильтраций при каждой перезагрузке странички...раз в минуту занес температуры в массив,а там работай с ними,выводи хоть на веб,хоть рассылай куда еще,не важно...
паняаааааатна.....