Arduino Polska Forum

Pełna wersja: Problem z OLED 128x64 (Adafruit_SSD1306 & Adafruit_GFX)
Aktualnie przeglądasz uproszczoną wersję forum. Kliknij tutaj, by zobaczyć wersję z pełnym formatowaniem.
Stron: 1 2
Masz piękny przykład buffer overflow w programie... Chociaż przyznam, że szukając tego błędu już sam zaczynałem wierzyć w czarną magię.

Zacznijmy od początku - sam błąd nie ma nic wspólnego z linijką i display.print(). Spróbuj usunąć to wyświetlanie, pewnie powiesz, że wtedy działa. Ale zobacz co będzie jeśli do deklaracji valveState dodasz volatile - błąd znowu się pojawi.

Przyczyna błędu nie ma nic wspólnego z display.print(), może poza tym, że jeśli usuwasz tę linię, to optymalizator usuwa całą zmienną valveState, bo nie jest nigdzie indziej używana i wtedy program działa poprawnie.

Jeśli chcesz zobaczyć, gdzie jest błąd to zmień valveChangeState na:
Kod:
void valveChangeState(int pin, int state){
  if (pin >= 5)
    Serial.println("Kaboom!");

  valveState[pin] = state;
  digitalWrite(pin, state == 1 ? HIGH : LOW);
}

Teraz zobaczysz co się dzieje - parametr pin to nie jest indeks, ale numer pinu i tutaj masz zapis poza zakresem valveState, co akurat wylądowało w wynikach...
Nice one!

Nie wiem czy bym na to wpadł... A na pewno nie na moim poziomie programowania na Arduino. 

Gwoli ścisłości zamieniłem:
Kod:
if(rainSensorValue[i] >= RAIN_SENSOR_OPEN){ //if value greater or equal open valve thrshole
      openValve(valvePin[i]); //open valve and save them state
      isAnyOpenedValve = true; //indicate that valve is opened
    }
    if(rainSensorValue[i] <= RAIN_SENSOR_CLOSE){
      closeValve(valvePin[i]);
    }


na 

Kod:
    if(rainSensorValue[i] >= RAIN_SENSOR_OPEN){ //if value greater or equal open valve thrshole
      openValve(i); //open valve and save them state
      isAnyOpenedValve = true; //indicate that valve is opened
    }
    if(rainSensorValue[i] <= RAIN_SENSOR_CLOSE){
      closeValve(i);
    }


oraz 
Kod:
void valveChangeState(int pin, int state){
  valveState[pin] = state;
  digitalWrite(pin, state == 1 ? HIGH : LOW);
}

na
Kod:
void valveChangeState(int valveNo, int state){
  valveState[valveNo] = state;
  digitalWrite(valveState[valveNo], state == 1 ? HIGH : LOW);
}


Dziękuję bardzo za pomoc.

P.S. z głowy znalazłeś błąd czy debugowałeś lokalnie? 


P.P.S. deklaracja i definicja zmiennych jest następująca
Kod:
int rainSensorPin[] = {A0, A1, A2, A3, A6}; //rain sesnors pins
int rainSensorValue[] = {0, 0, 0, 0, 0}; //rain sensor values

#define VALVE_OPEN 1
#define VALVE_CLOSE 0
int valvePin[] = {2, 3, 4, 5, 6};
int valveState[] = {VALVE_CLOSE, VALVE_CLOSE, VALVE_CLOSE, VALVE_CLOSE, VALVE_CLOSE};

Wywołanie błędnie działającej funkcji valveChangeState powodowało nadpisanie w rainSensorValue. Dlaczego nie nadpisało valvePin? Zmienne nie są układane po kolei w pamięci czy coś innego na to wpłynęło?

Cały kod:
Kod:
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define OLED_ADDR 0x3C  //defince OLED addres. Default was 0x3D and i thik it was adafruit default. But from aliexpress has onother athres. To find I2C address use I2Scanncer
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


#define RAIN_SENSOR_OPEN 1000
#define RAIN_SENSOR_CLOSE 400
int rainSensorPin[] = {A0, A1, A2, A3, A6}; //rain sesnors pins
int rainSensorValue[] = {0, 0, 0, 0, 0}; //rain sensor values

#define VALVE_OPEN 1
#define VALVE_CLOSE 0
int valvePin[] = {2, 3, 4, 5, 6};
int valveState[] = {VALVE_CLOSE, VALVE_CLOSE, VALVE_CLOSE, VALVE_CLOSE, VALVE_CLOSE};

#define PUMP_PIN 7

void setup() {
  Serial.begin(9600);

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) { // Address OLED
    Serial.println(F("SSD1306 allocation failed"));
  }

  for(int i = 0; i < 5; i++){
    pinMode(valvePin[i], OUTPUT);
  }
  pinMode(PUMP_PIN, OUTPUT);

  // Clear the buffer
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 32);
  display.println("Auto Garden v 0.1.");
  display.display();
  delay(500);
 
}

void printTableOnLCD(){
 
  //vertical lines for dashboard
  display.drawLine(01, 01, 01, 31, SSD1306_WHITE);
  display.drawLine(16, 01, 16, 31, SSD1306_WHITE);
  display.drawLine(31, 01, 31, 31, SSD1306_WHITE);
  display.drawLine(46, 01, 46, 31, SSD1306_WHITE);
  display.drawLine(61, 01, 61, 31, SSD1306_WHITE);
  display.drawLine(76, 01, 76, 31, SSD1306_WHITE);
  display.drawLine(91, 01, 91, 31, SSD1306_WHITE);
  //horizontal lines for dashboard
  display.drawLine(01, 01, 91, 01, SSD1306_WHITE);
  display.drawLine(01, 11, 91, 11, SSD1306_WHITE);
  display.drawLine(01, 21, 91, 21, SSD1306_WHITE);
  display.drawLine(01, 31, 91, 31, SSD1306_WHITE);
 
  //draw water lvl symbol
  display.setCursor(04, 13);
  display.print("W");
  //display.drawBitmap(02, 12, image_water, 5, 5, SSD1306_WHITE);
 
  //draw valve symbol
  display.setCursor(04, 23);
  display.print("P");
  //display.drawBitmap(02, 22, image_valve, 5, 5, SSD1306_WHITE);
 
  //draw pupmp symbol
  //display.drawBitmap(65, 1, image_pump, 21, 16, SSD1306_WHITE);
 
}

void fillTableByData(){
  Serial.print("In fillTableByData ");
  int tmpValveState;
  for(int i = 0; i < 5; i++){
    Serial.print(rainSensorValue[i]);
    Serial.print(" ");
   
    display.setCursor(18 + 15 * i, 13);
    display.print(rainSensorValue[i]/10, DEC);
    //valveState[i] == VALVE_OPEN ? 1 : 0;
    display.setCursor(18 + 15 * i, 23);
    tmpValveState = ((valveState[i] == VALVE_OPEN)
    ? 1 : 0);
    display.print(tmpValveState, DEC);
   
//    display.drawBitmap(12 + 10 * i, 22, valveState[i] == VALVE_OPEN ? image_on : image_off, 5, 5, SSD1306_WHITE);
  }
  Serial.println();
}

void loop() {
  int val = 0;
  bool isAnyOpenedValve = false;
  Serial.print("In messure loop values: ");
  for(int i = 0; i < 5; i++){
    rainSensorValue[i] = analogRead(rainSensorPin[i]); //read value of 'i' sensor
    Serial.print(rainSensorValue[i]);
    Serial.print(" ");
    if(rainSensorValue[i] >= RAIN_SENSOR_OPEN){ //if value greater or equal open valve thrshole
      openValve(i); //open valve and save them state
      isAnyOpenedValve = true; //indicate that valve is opened
    }
    if(rainSensorValue[i] <= RAIN_SENSOR_CLOSE){
      closeValve(i);
    }
  }
 
  Serial.println();
  display.clearDisplay();
  printTableOnLCD();
  fillTableByData();
  display.display();

  Serial.print("Above fillTableByData ");
  for(int i = 0; i < 5; i++){
    Serial.print(rainSensorValue[i]);
    Serial.print(" ");
  }
  Serial.println();

  if(isAnyOpenedValve){ //let's check if is any valve opened
    turnOnPump(); //if so then powe up pump! even if was switched on
  }else{
    turnOffPump(); //if no thet power off pump, even if was switched off
  }
 
  delay(100);
}

void turnOnPump(){
  Serial.println("Pump switch on");
  digitalWrite(PUMP_PIN, HIGH);
}

void turnOffPump(){
  Serial.println("Pump switch off");
  digitalWrite(PUMP_PIN, LOW);
}


void openValve(int pin){
  valveChangeState(pin, VALVE_OPEN);
}

void closeValve(int pin){
  valveChangeState(pin, VALVE_CLOSE);
}

void valveChangeState(int valveNo, int state){
  valveState[valveNo] = state;
  digitalWrite(valveState[valveNo], state == 1 ? HIGH : LOW);
}
Zauważyć błąd na podstawie samego kodu byłoby faktycznie bardzo ciężko... Myślałem że błąd to przepełnienie stosu, więc podłączyłem Arduino UNO i zaprogramowałem Twoim kodem. Nawet bez wyświetlacza pojawiały się błędy, więc postanowiłem poszukać gdzie jest problem.
Byłem bardzo zaskoczony, że to jednak nie brak pamięci, a później było już tylko długie poszukiwanie, jeśli nie stos, to o co może chodzić.
Co do adresów zmiennych w pamięci, to nie muszą być w tej kolejności jak zostały zadeklarowane w programie, u mnie faktycznie valvePin jest zaraz przed rainSensorPin:

00800106 l    O .data  0000000a valvePin
00800110 l    O .data  0000000a rainSensorPin
Ok. Dziękuję jeszcze raz za wyjaśnienia. Temat do zamknięcia.
Stron: 1 2