Зависание Arduino из-за кода

Marlen S
Offline
Зарегистрирован: 13.01.2015

 

Здравствуйте товарищи. Не могли бы Вы объянить мне что не так? Залив скетч из примеров ардуино работает как надо, но как только я заливаю данный скетч ардуино зависает, а проявляется это в следующем, часы могут просто залипать и выдать значения секунд или минут с запозданием. Так же после значения температуры появляются фантомные нули и так же показывает иногда -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);
}

 

За ранее Спасибо всем откликнувшимся.

 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

шины I2C резисторами 4,7 kOm к +5 V подтянули ? адреса пользователей I2C не конфликтуют ?

библиотеки строки 1 и 2 - совместимы ? длинные коды - сворачивать надо, хороший тон, схему подключения надо

а по отдельности пробовали все узлы погонять ?

Marlen S
Offline
Зарегистрирован: 13.01.2015

Да нонечно, 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...

 

Marlen S
Offline
Зарегистрирован: 13.01.2015

У меня практики то на ардуино да и вообще програмирования пару недель :(

bwn
Offline
Зарегистрирован: 25.08.2014

Ну во первых, если часы прилепили на lcd резисторы уже не нужны. И попробуйте не через гребенку часов а параллельно их включить. Код сворачивать - там галочка есть когда вставляете, чтобы вашу портянку по экрану не гонять.

Marlen S
Offline
Зарегистрирован: 13.01.2015

Спасибо, на счет портянки понял :) буду теперь знать.  Подключил паралельно, работает без зависаний, значит что то с часами не то, а вот почему фантомные нули появляются не пойму.

bwn
Offline
Зарегистрирован: 25.08.2014

Marlen S пишет:

Спасибо, на счет портянки понял :) буду теперь знать.  Подключил паралельно, работает без зависаний, значит что то с часами не то, а вот почему фантомные нули появляются не пойму.

Скорее какие то паразитные наводки при сквозном проходе.

Marlen S
Offline
Зарегистрирован: 13.01.2015

Не понял на счет наводок и сквозном проходе) разьясните на пальцах)

rustam
Offline
Зарегистрирован: 25.01.2015

Привет у меня не много опыта что бы проанализировать код, и что то подсказать, но мой совет в цикле 

void loop(){

}

Вставте больше выводов в терминал ( значения переменной, коментарий действий).

Serial.print( );

Serial.println( );

Очень облегчат диагностику.

Ну и для нас, будет больше информации.  

 

bwn
Offline
Зарегистрирован: 25.08.2014

Marlen S пишет:

Не понял на счет наводок и сквозном проходе) разьясните на пальцах)

Если как вы сказали, что после отключения линий со второй гребенки часов и подключения их просто параллельно проблема исчезла, значит что то происходит во время прохождения сигналов по плате часов.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

Marlen S пишет:

Не понял на счет наводок и сквозном проходе) разьясните на пальцах)

1 пин источник и 7 пинов приёмников , подключать надо семью проводами 1 - 2 , 1 - 3 , 1 - 4 ........... ,

а не - 1 - 2 - 3 - 4 -5 - 6 - 7 - 8..... так на крайнем пине будет сигнал от 1 и мусор-помехи от других пинов

Marlen S
Offline
Зарегистрирован: 13.01.2015

Я понял о чем Вы) с помехами я уже разобрался) но только что ds18b20 показывает -127 не погу понять. Если надо я могу припаять поключения к дуино без ножек, это поможет?

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

сделайте для него отдельный код, проверьте отдельно

Marlen S
Offline
Зарегистрирован: 13.01.2015

Я дико извеняюсь, что нет описания :( но код приметивен и думаю тут особо и разбиратся не с чем :) А зачем больше выводов в терминал?

Marlen S
Offline
Зарегистрирован: 13.01.2015

в стандартном примере даласа все работает нормально.

bwn
Offline
Зарегистрирован: 25.08.2014

Marlen S пишет:

Я понял о чем Вы) с помехами я уже разобрался) но только что ds18b20 показывает -127 не погу понять. Если надо я могу припаять поключения к дуино без ножек, это поможет?

Потеребите еще раз все контакты на DS-ке и резисторе. А он что то другое показывал кроме этого?

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

Marlen S пишет:

Я дико извеняюсь, что нет описания :( но код приметивен и думаю тут особо и разбиратся не с чем :) А зачем больше выводов в терминал?

имитация пошагового режима :)

Marlen S
Offline
Зарегистрирован: 13.01.2015

да, саму темпиратуру. Он работать может и минут 20, а бывает что тупо прыгает то привильно показыает то -127.

pastry777
Offline
Зарегистрирован: 16.01.2014

-127 означает нет контакта...если я не ошибаюсь,вы подтянули ножку питания датчика к ножке данных резистором 10к(ваш пост #2)..это много,по даташиту 4.7к,а в реальности обычно меньше,от 1.2к ну и до 4.7к...вобщем мой совет,попробуйте опытным путем уменьшите сопротивление подтяжки датчика...

Marlen S
Offline
Зарегистрирован: 13.01.2015

Заменил DS18b20 на другой, проблема изчезла, думаю что то с нам. но не пойму почему он работал отдельно :( сказывается опыт :(

pastry777
Offline
Зарегистрирован: 16.01.2014

вот это как раз симптомы не удачного сопротивления....я,кстати,у себя сделал програмную фильтрацию от значения -127,просто у меня на шине много датчиков и сама шина длинная,наводки,то се,полностью без ошибок не получается получать температуру с датчиков..в скетче отсеиваю ложные значения и все дела..

Marlen S
Offline
Зарегистрирован: 13.01.2015

Понял, начну с 1,2к на подтяжку. Просто где я взял кусок кода на 18b20 было указано что нужно подключать на 10к .

bwn
Offline
Зарегистрирован: 25.08.2014

И еще наводящий вопрос, у вас в коде есть релюшки, они физически сейчас щелкают?

Marlen S
Offline
Зарегистрирован: 13.01.2015

У меня конечно же не шлейф) а один) но все же, не могли бы Вы описать как вы отсеиваете ложные сигналы, что бы  это повторить у себя, кто значет быть может поможет.

Marlen S
Offline
Зарегистрирован: 13.01.2015

Да, они шелкают как надо, как по времени таки по темпиратуре. Знаю что в коде все может на первый взгляд выглядет что не правильно написано, но я Вас уверяю что се работает исправно)

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

лучше начинать с 4,7 и двигаться к 1,2 :)

bwn
Offline
Зарегистрирован: 25.08.2014

Marlen S пишет:

Да, они шелкают как надо, как по времени таки по темпиратуре. Знаю что в коде все может на первый взгляд выглядет что не правильно написано, но я Вас уверяю что се работает исправно)

В зависимости как они запитаны, тоже могут давать помеху на датчик, фантомные нули на lcd и прочее.

Marlen S
Offline
Зарегистрирован: 13.01.2015

Посадил на припой все провода ds18b20 и работает на ура :))) Резюк поставил на 4,7к. Осталовь все установить в  корпус сея устройства http://ru.aliexpress.com/item/12V-2A-24W-LED-Strip-Light-Switch-Power-Su...

и подключить нагрузку :) Чем уже и занят :) Всем ОГРОМНОЕ Спасибо за советы, без Вас не куда :)

pastry777
Offline
Зарегистрирован: 16.01.2014

ну вот вам огрызок с моего скетча

есть два массива: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];
     }
   } 

 

Marlen S
Offline
Зарегистрирован: 13.01.2015

Опытным путем я понял что не стоит питание реле питать от ардуино) ибо грелся ужасно сильно плата. После этого я отвел отдельное питание для них)

pastry777
Offline
Зарегистрирован: 16.01.2014

SU-27-16 пишет:

лучше начинать с 4,7 и двигаться к 1,2 :)

да,верное замечание=)

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

а зачем в массив ? чё не налету проверять ? ошибка - повторить опрос... а помнить только предзначение

Marlen S
Offline
Зарегистрирован: 13.01.2015

Спасибо :) за фильтр. Это чудо мне пригодится для следующего проектра где будут более 6 датчиков :)

pastry777
Offline
Зарегистрирован: 16.01.2014

делал и на лету,но повторить запрос,соответственно время на конвертацию,если глюкнуло пару датчиков,запинка будет ощутима...я посчитал,что в моих условия мне можно этим пренебречь..пока так,а там как подойду к стадии оптимизации кода,может и изменю=)

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

согласен.... только зачем массив ? запоминать одно крайнее верное - для отката, если текущее ошибочное :) ( без переопроса глюкнувшего датчика )

pastry777
Offline
Зарегистрирован: 16.01.2014

у меня над этим кодом прежде чем занести значение в inttemp я провожу проверку на валидность встроенной функцией sensors.validAddress и тд...так как шин датчиков у меня три,да еще и не в окончательном варианте все(адреса датчиков еще перекидую порой с шины на шину),просто одним циклом это все не обработать,а так код будет из многа строк и букаф=)я вашу идею понял,сводится к тому,что массив inttemp можно исключить и сэкономить тем самым 40 байт оперативки...чуть позжее займусь этим=)

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

:) 2 массива по 9 значений по 4 байта = 72

pastry777
Offline
Зарегистрирован: 16.01.2014

Массив temp должен быть полюбому,ведь веб-страничка может дергаться несколько раз в минуту,зачем мне опрашивать каждый раз датчики и проводить сотню фильтраций при каждой перезагрузке странички...раз в минуту занес температуры в массив,а там работай с ними,выводи хоть на веб,хоть рассылай куда еще,не важно...

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

паняаааааатна.....