Skocz do zawartości

Pomocna odpowiedź

Napisano (edytowany)

Wszystko działa dobrze, ale gdy temperatura spadnie poniżej 0 to pokazuje jakiś dziwny odczyt. Siedzę nad tym już drugi dzień i nie wiem o co chodzi. Używam arduino nano. Z góry dziękuję za pomoc 🙂

#include <ModbusRtu.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

#define SLAVE_ID 1
#define BUTTON_PIN 7
#define RS_PIN 5
#define DS_PIN 10
#define SUN_PIN A1
#define TEMP_REG 0
#define SUN_REG 1

uint16_t au16data[9] = {
  9999, 9999, 2, 3, 2018, 11, 16, 8, 7};

Modbus slave(SLAVE_ID, 0, RS_PIN);
OneWire oneWire(DS_PIN);
DallasTemperature sensors(&oneWire);
DeviceAddress ds18b20 = { 0x28, 0x90, 0x63, 0x45, 0x92, 0x06, 0x02, 0xE0 }; //1
//DeviceAddress ds18b20 = { 0x28, 0x68, 0xA6, 0x45, 0x92, 0x03, 0x02, 0x3C }; //2
//DeviceAddress ds18b20 = { 0x28, 0x12, 0xC6, 0x45, 0x92, 0x08, 0x02, 0x59 }; //3
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

int temperature = 9999;
unsigned long getTempTime = 0;
unsigned long lastUpdate = 0;
unsigned long buttonTime = 0;
int buttonHoldTime = 0;
byte sun = 0;
bool lcdLight = true;

void setup() {
  sensors.begin();
  slave.begin( 9600 ); // baud-rate at 9600
  lcd.begin(16,2); 
  pinMode(BUTTON_PIN, INPUT);
}

void loop() {
  temperature = readTemp(); 
  if(temperature != NULL || temperature < 200)
    au16data[TEMP_REG] = temperature;

  sun = readSun();
  if(sun != NULL)
    au16data[SUN_REG] = sun;
    
  slave.poll(au16data, 16);
  
    if(millis()-lastUpdate >= 1500UL)
    {
      lcd.clear();
      printTime();
      lcd.setCursor(0, 1);
      printPage0();
      lastUpdate = millis();
    }
    
  if(digitalRead(BUTTON_PIN) == HIGH){
    if(buttonTime == 0) 
      buttonTime = millis();
      
    buttonHoldTime += millis()-buttonTime;
    buttonTime = millis();
  }
  else{
    if(buttonHoldTime > 750){
      if(lcdLight == true)
        lcdLight = false;
      else lcdLight = true;
    }

    else if(buttonHoldTime < 500 && buttonHoldTime > 50)
      ;
      
    buttonHoldTime = 0;  
    buttonTime = 0;
  }

  if(lcdLight == true) lcd.backlight();
  else lcd.noBacklight();
//////////////////////////////////////
}

int readTemp(){
  
  if(millis()-getTempTime >= 1000UL){
    sensors.requestTemperatures();
    getTempTime = millis();
    return sensors.getTempC(ds18b20)*10;
  }
  else return temperature;
}

byte readSun(){
  return map(analogRead(SUN_PIN), 0, 1023, 0, 100);
}

void printTime(){
    if(au16data[7] < 10)
      lcd.print(0);
    lcd.print(au16data[7]);
    lcd.print(":");
    if(au16data[8] < 10)
      lcd.print(0);
    lcd.print(au16data[8]);
    lcd.print(" ");
    lcd.print(au16data[6]);
    lcd.print(".");
    lcd.print(au16data[5]);
    lcd.print(".");
    lcd.print(au16data[4]);
}

void printPage0(){
    lcd.print("T:");
    lcd.print(au16data[TEMP_REG]/10);
    lcd.print(".");
    lcd.print(au16data[TEMP_REG]-au16data[TEMP_REG]/10*10);
    lcd.print("*C");
    lcd.print(" ");
    lcd.print("SUN:");
    lcd.print(au16data[SUN_REG]);
    lcd.print("%");
}

 

50917540_233674164237651_2049659836483764224_n.jpg

Edytowano przez yersey

@yersey, jeśli dobrze rozumiem to temperaturę przechowujesz w tablicy au16data, zgadza się?

Zadeklarowałeś ją jako typ uint16_t czyli typ bez znaku (mówi o tym pierwsze literka "u" od "unsigned". Reasumując: ta tablica nie potrafi przetrzymywać ujemnych wartości. Musisz zmienić typ danych np. na int16_t lub po prostu na int. Dlaczego akurat wybrałeś taki typ jak uint16_t? To dość mało popularne jak na Arduino 😉 

  • Pomogłeś! 1

@Treker Biblioteka narzuca taki typ, ale to już nie problem, dodam po prostu kolejny element do tablicy oznaczający "minusowość" temperatury. Najważniejsze, że w końcu działa. Bardzo mi pomogłeś, dzięki 🙂

4 godziny temu, yersey napisał:

Biblioteka narzuca taki typ, ale to już nie problem, dodam po prostu kolejny element do tablicy oznaczający "minusowość" temperatury.

Nie, nie to brzmi bardzo źle - na pewno nie powinno się tak tego rozwiązywać.

O której bibliotece piszesz? Nie możesz po prostu zadeklarować tablicy w taki sposób, aby pozwalała na zapisywanie wartość ujemnych?

Myślałem pierwotnie, że to zwykłe wyświetlanie danych z czujników na LCD (nie analizowałem kodu), ale skoro masz tu Modbusa, to chyba jednak jest coś więcej. Możesz opisać czym dokładnie jest to urządzenie i co ono ma robić?

@Treker Będzie służyć do monitorowania głównie temperatury w tunelach foliowych (wcześniej trzeba było wstawać w nocy co kilka godzin, bo podajnik węgla potrafił się zaciąć, a jak temperatura by spadła to rip). Teraz wystarczy, że w którymś tunelu spadnie temperatura to w domu włączy się syrena. Mogę też sprawdzać temperaturę na wykresach. Nie jest to pewnie idealne, ale i tak jestem z siebie dumny i przy okazji nauczyłem się masę rzeczy 🙂

 


https://github.com/yersey/arduino-modbus-weather-station

  • Lubię! 1

Ok, teraz ma to większy sens, bo już się bałem, że to zwykły termometr, a masz tam jakieś dziwne rzeczy dorobione 😉

Jednak w takim razie to nic straconego. Możesz dane transmitować jako uint16, ale po odebraniu możesz je sobie rzutować na wersję ze znakiem. Przykład:

void setup() {
  Serial.begin(9600);
  delay(1000);
  
  uint16_t temp = -2;
  Serial.println(temp);
  int16_t temp2 = temp;
  Serial.println(temp2);
  Serial.println((int16_t)temp);
}



void loop() {
}

Możesz to zrobić na dwa sposoby (jak wyżej): możesz przypisać wartość uint16_t do zmiennej typu int16_t i przy wyświetlaniu posługiwać się tą nową zmienną lub możesz przy wyświetlaniu wstawić zapis "(int16_t)" przed nazwą zmiennej uint16_t 🙂 Daj znać czy rozwiązało problem.

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...