Помощь с передачей данных по Bluetooth

Тема в разделе "Arduino & Shields", создана пользователем Nikita_mv, 4 ноя 2019.

  1. Nikita_mv

    Nikita_mv Нерд

    Доброго времени суток! Помогите разобраться. Делаю устройство для управления котлом отопления. Градусник передает значения температуры через Bluetooth. С передачей проблем не возникает в мониторе порта значения четкие, а вот на приеме постоянно вылезает 255 градусов 2 градуса 2555, -138 градусов причем передатчик отрицательные числа вообще не передает. Ошибка висит не долго 1 - 5 сек всегда по разному но котел успевает включится либо выключится.
    Код принимающего устройства:
    Код (C++):
    #include <Wire.h>
    #include <LiquidCrystal_I2C.h>
    LiquidCrystal_I2C lcd(0x3F,16,2);  // Устанавливаем дисплей
    byte simvol[8]   = {B11100,B10100,B11100,B00000,B00000,B00000,B00000,B00000,}; // Символ градуса
    int datB=7; // датчик бойер

    const int datT=9;// комнатный термостат

    int rele_1 =10; // питание клапана
    int rele_2 = 12; // питание насос
    int Temp; // освобождаем память для переменной "temp"

    int settemp;
    int flag; //состояние

    unsigned long currentTime;

    int t;

    void setup() {
      // put your setup code here, to run once:
    pinMode (datB, INPUT);

    pinMode (datT, OUTPUT);
    pinMode (rele_1, OUTPUT);
    pinMode (rele_2, OUTPUT);

    flag=1;
    settemp=22;

    lcd.init();                    
     
    // lcd.print("iarduino.ru");
    //  lcd.setCursor(8, 1);
    // lcd.print("LCD 1602");

       Serial.begin(9600);


    }

    void loop() {
    if(Serial.available() >0) {//если в порт пришли данные
    t = Serial.parseInt();
      if(t>0||t<40){                                                //защита от ошибочных
      Temp= t;                                                      //   данных НЕ РАБОТАЕТ
      }
    }

    Serial.print( t);                //
    Serial.println("b");           //  
    Serial.print (Temp);          //      Контроль
    Serial.println("Temp");     //
    // Serial.print(b);              //
    delay(1000);                


    lcd.clear();
    lcd.backlight();// Включаем подсветку дисплея
       lcd.setCursor(0, 0);
      lcd.print("Temperatura");

    lcd.createChar(1, simvol);                  // Создаем символ под номером 1
    lcd.setCursor(0,1);                         // Устанавливаем курсор на 2 строку, ячейка 1
      lcd.print(Temp);      // Выводим показания температуры
      lcd.setCursor(14,1);
       lcd.setCursor(3,1);                        // Устанавливаем курсор на 2 строку, ячейка 6
      lcd.print("\1");                            // Выводим символ градуса
      lcd.setCursor(4,1);                        // Устанавливаем курсор на 2 строку, ячейка 7
      lcd.print("C");                             // Выводим текст
      lcd.setCursor(11,1);
      lcd.print(flag);

    delay(1000); // ставим небольшую задержку

    if ( digitalRead(datB)==LOW&&(Temp>=settemp+1)) {// если бойлер горячий в дома тепло
            flag=1;
      }

    if ( digitalRead(datB)==HIGH&&(Temp>=settemp+1)){//если бойлер холодный в доме тепло
          flag=2;
    }
    if ( Temp <=settemp){//если  в доме холодно
          flag=3;

    }
    if ( Temp <settemp && digitalRead(datB)==HIGH){//если  в доме холодно и бойлер холодный
          flag=4;

    }

      if (flag==1){
     
         digitalWrite (datT, LOW);//разамкнуть датчик термостата
         delay(300);
        digitalWrite (rele_1, LOW);//открыть клапан отопления
        delay(300);
      digitalWrite (rele_2, LOW); // откл. насос бойера
       
        if(millis()-currentTime>31000){
          currentTime=millis();
        digitalWrite(datT, HIGH);
       delay(2000);
         digitalWrite (datT, LOW);
       
      }

    //digitalWrite (datU, LOW);
      }
     
    if (flag==2){    
      digitalWrite (rele_2, HIGH); // вкл. насос бойера
      delay(300);
      digitalWrite (rele_1, HIGH);//закрыли клапан отопления
      delay(300);
      digitalWrite (datT, HIGH);//зомкнуть датчик термостата
    //digitalWrite (datU, LOW);
      }


    if (flag==3){

      digitalWrite (rele_1, LOW);//открыть клапан отопления
      digitalWrite (rele_2, LOW); // откл. насос бойера
      digitalWrite (datT, HIGH);//разомкнуть датчик термостата
      if (Temp>=23){
          digitalWrite (datT, LOW);//разамкнули датчик термостата
      }
      }
    //digitalWrite (datU, LOW);
     
    if (flag==4){
       digitalWrite (rele_2, HIGH); // вкл. насос бойера
       delay(300);
      digitalWrite (rele_1, HIGH);// закрыть клапан отопления
      delay(300);
      digitalWrite (datT, HIGH);//замкнуть датчик термостата
     
     
    //digitalWrite (datU, LOW);

    }





     

    }





    Код передающего устройства:

    Код (C++):
    #include <OneWire.h>
    #include <Wire.h>
    #include <DallasTemperature.h>
    #define DS18B20 2                           // Указываем, к какому выводу подключена DQ

    OneWire oneWire(DS18B20);                  
    DallasTemperature sensors(&oneWire);
    int rst =6;    //питание датчика
    int t;
    //byte a;
    void setup() {
       Serial.begin(9600);
       pinMode (rst,OUTPUT);
       digitalWrite(rst,HIGH);
    }

    void loop() {
    sensors.requestTemperatures();   // читаем температуру
    if (sensors.getTempCByIndex(0)>0){  // если значение боьше нуя
    t=sensors.getTempCByIndex(0);//*100;       // сохраняем  данные
    }

    Serial.println(t); // отправить  в порт
    delay(1000);

    if (sensors.getTempCByIndex(0)<=-100) {
      digitalWrite(rst,LOW);
      delay(300);
      digitalWrite(rst,HIGH);
    }


    }
     
  2. Daniil

    Daniil Гуру

    я бы тут поставил И.
    Всегда прут ложные данные или иногда? Если всегда, то надо проверять подключение. Если иногда, то, как гипотеза, что произойдёт если данные приходят, но еще не пришли все?
    Я бы делал через serialEvent (см. в примерах) и ограничивал пачку данных какими-нибудь символами.
    Чтобы когда данные придут не сразу ломиться их обрабатывать, а дождаться, что пришел символ начала пачки, а когда придет символ конца пачки. Между ними будут данные. Если случился сбой, то стереть буфер и ждать следующей пачки. Реализацию я где-то на форуме приводил.
     
  3. Nikita_mv

    Nikita_mv Нерд

    С начало "И" ставил результат тот же. сбои периодические но постоянные)
    хорошая идея

    Код (C++):
    String inputString = "";         // строка, в которую будут записываться входящие данные
    //int inputTemp ;
    boolean stringComplete = false;  // заполнилась ли строка или нет
    void setup() {
    Serial.begin(9600);
    inputTemp.reserve(200);
    }

    void serialEvent() {
      while (Serial.available()) {
        // получаем новый байт:
        char inChar = (char)Serial.read();
        // добавляем его к inputString:
        inputString  += inChar;
        // если получили символ новой строки, оповещаем программу об этом,
        // чтобы она могла принять дальнейшие действия.
        if (inChar == '\n') {
          stringComplete = true;
        }
      }
    }

    void loop() {

    // если прибыл символ новой строки, показываем строку:
      if (stringComplete) {
        Serial.println(inputString);
        // очищаем строку:
        inputString = " ";
        stringComplete = false;

      }


    }



    Но как теперь из
    Код (C++):
    String
    сделать
    Код (C++):
    int
    [/QUOTE]
     
  4. Daniil

    Daniil Гуру

    тут просто условие, извиняюсь, глупое. Все числа от -бесконечности до + бесконечности пройдут его)
    Если сбои появляются временами, то я подозреваю на рассинхронизацию према.
    Если это так, то лучше идти путем введения избыточности и маркеров в протокол передачи данных, что я и советовал ранее.
    Как делать из стрингов инты написано не раз во всех обучающих материалах и описании библиотеки String, но я бы советовал поискать тут.
     
  5. issaom

    issaom Гуру

    А зачем вообще числа передавать буквами? Все эти Ардуиновские parseInt() и прочая фигня хороши для мигания светодиодами и обучения - в готовых устройствах пользоваться тем что не понятно как работает изнутри извращение.
     
    parovoZZ и Daniil нравится это.
  6. b707

    b707 Гуру

    Что-то не вижу у вас в коде, зачем это делать

    А так коллеги правильно сказали - отправляйте значение температуры одним байтом командой Serila.write(). принимайте Serial.read() - и даже SerialEvent не нужен будет
     
  7. Nikita_mv

    Nikita_mv Нерд

    Спасибо все получилось!:)