Зависание 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 резисторы уже не нужны. И попробуйте не через гребенку часов а параллельно их включить. Код сворачивать - там галочка есть когда вставляете, чтобы вашу портянку по экрану не гонять.
Спасибо, на счет портянки понял :) буду теперь знать. Подключил паралельно, работает без зависаний, значит что то с часами не то, а вот почему фантомные нули появляются не пойму.
Спасибо, на счет портянки понял :) буду теперь знать. Подключил паралельно, работает без зависаний, значит что то с часами не то, а вот почему фантомные нули появляются не пойму.
Скорее какие то паразитные наводки при сквозном проходе.
Не понял на счет наводок и сквозном проходе) разьясните на пальцах)
Привет у меня не много опыта что бы проанализировать код, и что то подсказать, но мой совет в цикле
Вставте больше выводов в терминал ( значения переменной, коментарий действий).
Очень облегчат диагностику.
Ну и для нас, будет больше информации.
Не понял на счет наводок и сквозном проходе) разьясните на пальцах)
Если как вы сказали, что после отключения линий со второй гребенки часов и подключения их просто параллельно проблема исчезла, значит что то происходит во время прохождения сигналов по плате часов.
Не понял на счет наводок и сквозном проходе) разьясните на пальцах)
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..все чем я рискую,если была ошибка,то просто отображаемая температура с датчика который в данный опрос дал ошибку,будет устаревшая на минуту=))
Опытным путем я понял что не стоит питание реле питать от ардуино) ибо грелся ужасно сильно плата. После этого я отвел отдельное питание для них)
лучше начинать с 4,7 и двигаться к 1,2 :)
да,верное замечание=)
а зачем в массив ? чё не налету проверять ? ошибка - повторить опрос... а помнить только предзначение
Спасибо :) за фильтр. Это чудо мне пригодится для следующего проектра где будут более 6 датчиков :)
делал и на лету,но повторить запрос,соответственно время на конвертацию,если глюкнуло пару датчиков,запинка будет ощутима...я посчитал,что в моих условия мне можно этим пренебречь..пока так,а там как подойду к стадии оптимизации кода,может и изменю=)
согласен.... только зачем массив ? запоминать одно крайнее верное - для отката, если текущее ошибочное :) ( без переопроса глюкнувшего датчика )
у меня над этим кодом прежде чем занести значение в inttemp я провожу проверку на валидность встроенной функцией sensors.validAddress и тд...так как шин датчиков у меня три,да еще и не в окончательном варианте все(адреса датчиков еще перекидую порой с шины на шину),просто одним циклом это все не обработать,а так код будет из многа строк и букаф=)я вашу идею понял,сводится к тому,что массив inttemp можно исключить и сэкономить тем самым 40 байт оперативки...чуть позжее займусь этим=)
:) 2 массива по 9 значений по 4 байта = 72
Массив temp должен быть полюбому,ведь веб-страничка может дергаться несколько раз в минуту,зачем мне опрашивать каждый раз датчики и проводить сотню фильтраций при каждой перезагрузке странички...раз в минуту занес температуры в массив,а там работай с ними,выводи хоть на веб,хоть рассылай куда еще,не важно...
паняаааааатна.....