Arduino Polska Forum

Pełna wersja: Arduino UNO+Oled1106+bluetooth Xm15B (Rozwiązany)
Aktualnie przeglądasz uproszczoną wersję forum. Kliknij tutaj, by zobaczyć wersję z pełnym formatowaniem.
Witam.
Buduję projekt termometru bazującego na czujnikach DS18B20 przy tym wykorzytując moduł bluetooth xm15b do komunikacji z telefonem a dokładniej virtuino. Sam program w takiej konfiguracji działa dobrze jednak chcę dołożyć obsługę wyświetlacza oled SH1106 z komunikacją i2C. Po złożeniu kodu dla obsługi samego wyświetlacza i zczytywaniu danych z czujników ta część programu również działa dobrze. Problem mój zaczyna się w momencie sklejenia tych dwóch części programu do kupy, moja wiedza jest początkująca w zakresie programowania ale z tego co zauważyłem program gubi się przy inicjalizacji ekranu. wrzucę 3 kody pierwszy to kod obsługujący temperaturę bluetooth i virtuino, drugi obługuje temperaturę i oled a trzeci to złożenie obu do kupy.

Kod:
#include <OneWire.h>
#include <DallasTemperature.h>
#include "VirtuinoBluetooth.h"   
#include <SoftwareSerial.h>  

#define ONE_WIRE_BUS 6

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
SoftwareSerial bluetoothSerial =  SoftwareSerial(2,3);  
VirtuinoBluetooth virtuino(bluetoothSerial);      
//======================================================================== setup

void setup(void){
  Serial.begin(9600);    
 
bluetoothSerial.begin(9600); 
  virtuino.DEBUG=true;        
  sensors.begin();
  Serial.println("Setup complete.");
 
}

//======================================================================== setup
void readTemperatures(){

  Serial.println(" Requesting temperatures...");
  sensors.requestTemperatures();
  Serial.println("DONE");

  float temperature1=sensors.getTempCByIndex(0);
  float temperature2=sensors.getTempCByIndex(1);
  float temperature3=sensors.getTempCByIndex(2);
  float temperature4=sensors.getTempCByIndex(3);
  float temperature5=sensors.getTempCByIndex(4);
  float temperature6=sensors.getTempCByIndex(5);
  float temperature7=sensors.getTempCByIndex(6);
  Serial.println("Temperature for Device 1 is: "+String(temperature1));
  Serial.println("Temperature for Device 2 is: "+String(temperature2));
  Serial.println("Temperature for Device 3 is: "+String(temperature3));
  Serial.println("Temperature for Device 4 is: "+String(temperature4));
  Serial.println("Temperature for Device 5 is: "+String(temperature5));
  Serial.println("Temperature for Device 6 is: "+String(temperature6));
  Serial.println("Temperature for Device 7 is: "+String(temperature7));

  virtuino.vMemoryWrite(0,temperature1);   
  virtuino.vMemoryWrite(1,temperature2);
  virtuino.vMemoryWrite(2,temperature3);
  virtuino.vMemoryWrite(3,temperature4);
  virtuino.vMemoryWrite(4,temperature5);
  virtuino.vMemoryWrite(5,temperature6);
  virtuino.vMemoryWrite(6,temperature7);

}

void loop(void){
  virtuino.run(); 

  readTemperatures();
  virtuino.vDelay(1000);

}
kod nr 2:
Kod:
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
#include <OneWire.h>
#include <DallasTemperature.h>

/* Uncomment the initialize the I2C address , uncomment only one, If you get a totally blank screen try the other*/
#define i2c_Address 0x3c //initialize with the I2C addr 0x3C Typically eBay OLED's
//#define i2c_Address 0x3d //initialize with the I2C addr 0x3D Typically Adafruit OLED's

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1   //   QT-PY / XIAO
#define ONE_WIRE_BUS 6
Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

void setup()   {

  Serial.begin(9600);
 
  // Show image buffer on the display hardware.
  // Since the buffer is intialized with an Adafruit splashscreen
  // internally, this will display the splashscreen.

  delay(250); // wait for the OLED to power up
  display.begin(i2c_Address, true); // Address 0x3C default
//display.setContrast (0); // dim display

  display.display();
  delay(2000);

  // Clear the buffer.
  display.clearDisplay();
}
void loop() {

  Serial.println(" Requesting temperatures...");
  sensors.requestTemperatures();
  Serial.println("DONE");

  float temperature1 = sensors.getTempCByIndex(0);
  float temperature2 = sensors.getTempCByIndex(1);
  float temperature3 = sensors.getTempCByIndex(2);
  float temperature4 = sensors.getTempCByIndex(3);
  float temperature5 = sensors.getTempCByIndex(4);
  float temperature6 = sensors.getTempCByIndex(5);
  float temperature7 = sensors.getTempCByIndex(6);


  display.setTextSize(1);
  display.setTextColor(SH110X_WHITE);
  display.setCursor(25, 0);
  display.println("Termometr PRO");
  display.setTextColor(SH110X_WHITE);
  display.print("Tk=");
  display.print(temperature1);
  display.print(", T10=");
  display.println(temperature2);
  display.print("T1/2=");
  display.println(temperature3);
  display.print("Twej=");
  display.print(temperature4);
  display.print(", Twyj");
  display.println(temperature5);
  display.print("T_gl=");
  display.print(temperature6);
  display.display();
  display.clearDisplay();
}
i kod sklejany  (skróciłem go do obsługi jednego czujnika dla czytelności:

Kod:
#include <OneWire.h>
#include <DallasTemperature.h>
#include "VirtuinoBluetooth.h"   
#include <SoftwareSerial.h>
#include <SPI.h>
#include <Wire.h> 
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>

#define ONE_WIRE_BUS 6
/* Uncomment the initialize the I2C address , uncomment only one, If you get a totally blank screen try the other*/
#define i2c_Address 0x3c //initialize with the I2C addr 0x3C Typically eBay OLED's
//#define i2c_Address 0x3d //initialize with the I2C addr 0x3D Typically Adafruit OLED's
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1   //   QT-PY / XIAO

Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
SoftwareSerial bluetoothSerial =  SoftwareSerial(2,3);  
VirtuinoBluetooth virtuino(bluetoothSerial);      
//======================================================================== setup

void setup(){
  Serial.begin(9600);
  
 
bluetoothSerial.begin(9600); 
  virtuino.DEBUG=true;        
  sensors.begin();
  Serial.println("Setup complete.");
  
  // Show image buffer on the display hardware.
  // Since the buffer is intialized with an Adafruit splashscreen
  // internally, this will display the splashscreen.


  delay(1500); // wait for the OLED to power up
  display.begin(i2c_Address, true); // Address 0x3C default
//display.setContrast (0); // dim display
   display.display();
  delay(2000);

  // Clear the buffer.
  display.clearDisplay();
}

//======================================================================== setup
void readTemperatures(){

  Serial.println(" Requesting temperatures...");
  sensors.requestTemperatures();
  Serial.println("DONE");

  float temperature1=sensors.getTempCByIndex(0);

  Serial.println("Temperature for Device 1 is: "+String(temperature1));
 
  display.setTextSize(1);
  display.setTextColor(SH110X_WHITE);
  display.setCursor(25, 0);
  display.println("Termometr PRO");
  display.setTextColor(SH110X_WHITE);
  display.print("Tk=");
  display.print(temperature1);

  virtuino.vMemoryWrite(0,temperature1);   


}

void loop(){
  virtuino.run(); 

  readTemperatures();
  virtuino.vDelay(1000);

}
Jak ktoś mógłby cos podpowiedzieć będę wdzięczny, póki co jestem świeży w tym temacie i sporo korzystam z gotowców dostosowując je pod siebie, ale od kilku dni z tym walcze i już kończą się pomysły, gdzieś na forum angielskim znalazłem coś że chodzi o pin resetu w arduino jednak nie bardzo mi idzie znalezienie informacji co z tym mogę zrobić, a może arduino uno jest nie wystarczające?

pozdrawiam i z góry dzięki za fatygę.
display.display();
(09-10-2023, 21:55)kaczakat napisał(a): [ -> ]display.display();
Faktycznie na końcu zapomniałem o tym. Tylko że po inicjacji bluetooth i wyswietleniu setup complete w monitorze portu szeregowego program nie inicjuje wyswietlacza, a powinno się pojawić loga adafruit, tylko wykonuje delay i ponawia napis setup complete i tak cały czas jak zmienie czas dla delay to zmienia się tylko częstotliwość pojawiania napisu w monitorze setup complete a reszta się nie wykonuje. Dziś popołudniu dopiszę display.display tylko mam wrażenie że problem jest w funkcji void (setup).
Setup jest najłatwiejszy do ogarnięcia przy sklejaniu, wystarczy z dwóch projektów nie dublować rzeczy, jak masz w jednym np. Serial begin i w drugim to wybrać jeden. Możesz też zamienić kolejność. Zabawa zaczyna się dopiero w LOOP.

Z Twojego opisu wynika, że Arduino dochodzi do tego momentu i robi reset, skoro ponownie wyświetla "setup complete" - powinno tylko raz, możliwe że ma za mało RAM, OLED w tej bibliotece jest w pełni buforowany, to od razu zabiera połowę RAM, w sumie to powinno działać, nie widzę tam innych pożeraczy RAM.
Ale z Virtuino też nie korzystam, więc nie wiem co on robi z RAM w trakcie działania. Zainstalowałem te biblioteki i całość zajmuje 67%, teoretycznie jest to bezpieczny poziom, ale są biblioteki do tego OLED, zajmujące mniej RAM. Jak znajdę ten ekranik to przetestuję.
Może adres masz inny, wgrywasz z powrotem działający kod i rusza?
niestety tak jak się spodziewałem po dopisaniu display.display dalej nie działa,poniżej aktualny kod. ktoś może ma jakieś pomysły? Próbowałem już zmiany w funkcji void setup ale nie ma żadnych efektów. Z monitora portu szeregowego:
Kod:
Setup complete.
Se

Kod:
#include <OneWire.h>
#include <DallasTemperature.h>
#include "VirtuinoBluetooth.h"   
#include <SoftwareSerial.h>
#include <SPI.h>
#include <Wire.h> 
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>

#define ONE_WIRE_BUS 6
/* Uncomment the initialize the I2C address , uncomment only one, If you get a totally blank screen try the other*/
#define i2c_Address 0x3c //initialize with the I2C addr 0x3C Typically eBay OLED's
//#define i2c_Address 0x3d //initialize with the I2C addr 0x3D Typically Adafruit OLED's
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1   //   QT-PY / XIAO

Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
SoftwareSerial bluetoothSerial =  SoftwareSerial(2,3);   
VirtuinoBluetooth virtuino(bluetoothSerial);       
//======================================================================== setup

void setup(){
  bluetoothSerial.begin(9600); 
  virtuino.DEBUG=true;         
  sensors.begin();
 
  Serial.begin(9600);
  Serial.println("Setup complete.");


  delay(2000); // wait for the OLED to power up
  display.begin(i2c_Address, true); // Address 0x3C default
   //display.setContrast (0); // dim display
  display.display();
  // Clear the buffer.

  delay(2000);
  display.clearDisplay();
 

   
  // Show image buffer on the display hardware.
  // Since the buffer is intialized with an Adafruit splashscreen
  // internally, this will display the splashscreen.
}




void readTemperatures(){

  Serial.println(" Requesting temperatures...");
  sensors.requestTemperatures();
  Serial.println("DONE");

  float temperature1=sensors.getTempCByIndex(0);

  Serial.println("Temperature for Device 1 is: "+String(temperature1));
 
  display.setTextSize(1);
  display.setTextColor(SH110X_WHITE);
  display.setCursor(25, 0);
  display.println("Termometr PRO");
  display.setTextColor(SH110X_WHITE);
  display.print("Tk=");
  display.print(temperature1);
  display.display();
  delay(2000);
  // Clear the buffer.
  display.clearDisplay();
  virtuino.vMemoryWrite(0,temperature1);   


}

void loop(){
  virtuino.run(); 

  readTemperatures();
  virtuino.vDelay(1000);

}
Tak jak wrzucam działający kod czyli wersję gołą dla samego wyświetlacza to działa przykłady z biblioteki też działają. Jeszcze spróbuję na arduino nano i zamówiłem arduino mega więc jutro być może będę mógł potwierdzić wersję z za małą ilością pamięci ram. Wywalenie z kodu samego virtuino nic nie zmienia. Próbowałem ogarnąć na starych bibliotelach sh1106 ale tam mam info o przekroczwniu pamięci więc lipa natomiast u8glib nie bardzo jeszcze ogarniam na szybko więc chwilowo odpuściłem tą bibliotekę. Wygląda na to że arduino się resetuje zanim jeszcze przejdzie do funkcji loop bo nie zczytuje temperatury i nie wyświetla jej w monitorze.
Nie znalazłem SSH1106, ale zamieniłem oled na ssd1360 i faktycznie jest mało pamięci, na MEGA kod rusza, na NANO funkcja inicjująca ekran ma sprawdzenie czy alokacja się udała:
if(!display.begin(SSD1306_SWITCHCAPVCC, i2c_Address)) {
Serial.println(F("SSD1306 allocation failed"));
for(;Wink; // Don't proceed, loop forever
}
i drukuje że failed.
Coś ten Virtuino zżera ram.
Natomiast samo begin sprawia, że ekran jest martwy, ale na serial drukuje mi pomiary temperatury, tzn. -127, bo DS nie podłączałem już.
Zamiast kupować MEGA, jeśli potrzebujesz tylko OLED i DS możesz spokojnie kupić ESP8266, te ekrany spokojnie działają na 3.3V, no w sumie to bardziej SSD testowałem, ale powinno być to samo, gdzieś w okolicach 2.4V przestawał działać. Wemos Mini np., a poza tym, możesz wgrać wtedy Tasmota, ustawić, że używasz Oled i DS, w ogóle nie musisz programu pisać, a można tym sterować przez stronę interfejsu WWW.
Z innej beczki to do SSD1306 mam bibliotekę SSD1306 ASCII, ona w ogóle nie buforuje ekranu, jest tylko do wyświetlania tekstów, więc wysłanie tekstu z pamięci, jeszcze umieszczonego we flash to około 50B. Niestety dla SH widzę tylko opcję obsługi w SPI, ale może da się i ruszyć na I2C.
A idąc dalej, skoro jest taka jedna to na pewno znajdziesz na pęczki podobnych do SH.
Sukces Smile. Piszę dla potomnych żeby nie było. Kod programu napisany jest poprawnie, Po zmianie na Arduino mega wszystko śmiga trzeba pamiętać tylko o tym że w mega względem UNO inaczej trzeba podpiąć bluetooth wykorzystując softwareserial (u mnie to są w mega piny 10,11), oraz wyświetlacz pod piny sda, scl (u mnie 20,21). Dokładnej przyczyny nie mam ale wygląda to tak jak napisał Kaczakat że być może brakuje Ram pomimo poprawnej kompilacji programu na arduino Uno i dość bezpiecznych progach jeżeli chodzi o wykorzystanie pamięci. Wstawiam aktualnie wgrany wsad który chodzi w 100% jak potrzeba na ARDUINO MEGA 2560:
Kod:
#include <OneWire.h>
#include <DallasTemperature.h>
#include "VirtuinoBluetooth.h"   
#include <SoftwareSerial.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>

#define ONE_WIRE_BUS 6
/* Uncomment the initialize the I2C address , uncomment only one, If you get a totally blank screen try the other*/
#define i2c_Address 0x3c //initialize with the I2C addr 0x3C Typically eBay OLED's
//#define i2c_Address 0x3d //initialize with the I2C addr 0x3D Typically Adafruit OLED's
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1   //   QT-PY / XIAO

Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
SoftwareSerial bluetoothSerial =  SoftwareSerial(10,11);   
VirtuinoBluetooth virtuino(bluetoothSerial);       
//======================================================================== setup

void setup(){


  Serial.begin(9600);
  Serial.println("Setup complete.");


  delay(250); // wait for the OLED to power up
  display.begin(i2c_Address, true); // Address 0x3C default
   //display.setContrast (0); // dim display
  display.display();
  // Clear the buffer.

  delay(2000);
  display.clearDisplay();
  bluetoothSerial.begin(9600);
  virtuino.DEBUG=true;         
  sensors.begin();

   
  // Show image buffer on the display hardware.
  // Since the buffer is intialized with an Adafruit splashscreen
  // internally, this will display the splashscreen.
}

void loop(){
  virtuino.run();
  Serial.println(" Requesting temperatures...");
  sensors.requestTemperatures();
  Serial.println("DONE");

  float temperature1 = sensors.getTempCByIndex(0);
  float temperature2 = sensors.getTempCByIndex(1);
  float temperature3 = sensors.getTempCByIndex(2);
  float temperature4 = sensors.getTempCByIndex(3);
  float temperature5 = sensors.getTempCByIndex(4);
  float temperature6 = sensors.getTempCByIndex(5);
  float temperature7 = sensors.getTempCByIndex(6);
  virtuino.vMemoryWrite(0,temperature1);   
  virtuino.vMemoryWrite(1,temperature2);
  virtuino.vMemoryWrite(2,temperature3);
  virtuino.vMemoryWrite(3,temperature4);
  virtuino.vMemoryWrite(4,temperature5);
  virtuino.vMemoryWrite(5,temperature6);
  virtuino.vMemoryWrite(6,temperature7);
  Serial.println("Temperature for Device 1 is: "+String(temperature1));
  Serial.println("Temperature for Device 2 is: "+String(temperature2));
  Serial.println("Temperature for Device 3 is: "+String(temperature3));
  Serial.println("Temperature for Device 4 is: "+String(temperature4));
  Serial.println("Temperature for Device 5 is: "+String(temperature5));
  Serial.println("Temperature for Device 6 is: "+String(temperature6));
  Serial.println("Temperature for Device 7 is: "+String(temperature7));

  display.setTextSize(1);
  display.setTextColor(SH110X_WHITE);
  display.setCursor(25, 0);
  display.println("Termometr PRO");
  display.setTextColor(SH110X_WHITE);
  display.print("Tk=");
  display.print(temperature1);
  display.print(", T10=");
  display.println(temperature2);
  display.print("T1/2=");
  display.println(temperature3);
  display.print("Twej=");
  display.print(temperature4);
  display.print(", Twyj");
  display.println(temperature5);
  display.print("T_gl=");
  display.print(temperature6);
  display.display();
  display.clearDisplay();

  virtuino.vDelay(1000);
}
Bo ekran sobie alokuje pamięć na bufor już po starcie programu, a jak nie ma wolnego miejsca to jest ten komunikat failed. W MEGA nie musisz używać softserial, masz 4 sprzętowe, wywalasz wszystko do softserial i np inicjujesz VirtuinoBluetooth virtuino(Serial2); - teoretycznie, po napisaniu sprawdziłem i wywala błąd, ale jest przykład w bibliotece Virduino dla MEGA_DUE_example i tam jest wyjaśnione, że:
// Arduino Mega settings -> Open VirtuinoBluetooth.h file on the virtuino library folder -> disable the line: #define BLUETOOTH_USE_SOFTWARE_SERIAL
trzeba zakomentować jedną linię w tym pliku, zapisać, masz wtedy możliwość ustawić spokojnie 115200, albo po prostu cieszyć się, że program działa szybciej z buforowaniem UART.