I am attempting to combine the LoRa code from Module 6, Unit 2 with the sensor code of Module 4, Unit 8. This would allow receipt of sensor data using the BME280 via LoRa. But I’m getting the error “no matching function for call to ‘Adafruit_SSD1306.print()’ “. I’m still uncertain this approach will work.
Would you take a brief look at the code to see if I’m on track for both sides and any suggestions how I can get it to work? There are probably a number of other coding problems since I’m new, so I’m just wondering if it can be done.
Sender
https://drive.google.com/open?id=1CFtJpfvmeOgOQw3GxafMFKkvEaVgtm_T
Receiver
https://drive.google.com/open?id=1Irh8oVotWkxifMYCnNMbRBkfQ8b1-8vx
Hi Jack.
Yes, it is possible.
But your code is not well implemented.
You’re sending the readings via LoRa, but the receiver doesn’t know which reading it is receiving.
Additionally, you get that error because you’re defining Temperature, Pressure, Humidity and Altitude variables that are not used elsewhere. These are not saving the incoming LoRa readings.
On the sender side, you need to concatenate all the readings in one single message. Then, in the receiver side, split that message and save each reading on the corresponding variable.
To do what you want, I recommend taking a look at the sender code of this project to see how to concatenate the messages: https://randomnerdtutorials.com/esp32-lora-sensor-web-server/
And then, take a look at the receiver code, specially the getLoRaData() function that gets the data, splits the message and saves each reading on the corresponding variable. You can ignore the web server code.
Try figuring out for yourself. Then, if you need further help to make it work, just let me know.
I hope this helps.
Regards,
Sara
Thanks for taking time to look at it, Clearly I have just a very basic knowledge of coding, but will work at it let you know how it goes.
Jack
Ah, perhaps I have bitten off more than I can chew. I think I applied the concatenation properly (?), but the referenced lesson by Rui uses a different board that incorporates LoRa and OLED, whereas I am just following the configuration of Module 6 using the DOIT dev board and Adafruit RFM95/BoB. It is choking on how to set up the BME280. Module 4 is using I2C, whereas Module 6 uses SPI. So a lot for me to sort out. Somehow I need to design the code in chunks so it doesn’t matter what Unit lesson I’m drawing from, but I’m not there yet.
Also, I’m now confused why Module 4/Unit 8 wiring shows GPIOs 21/22 yet not referenced in the code.
https://drive.google.com/open?id=1rZOzGZbA5U8Ixnx3vLq7QZW1jnPL_i13
Unless you have time to help, I guess I’ll wait until I get to Project 4. As usual, your help is appreciated.
Hi Jack.
The example I show you also uses an OLED display. If you don’t want an OLED display on the Sender side, you just need to remove the lines that use the display.
You were missing the BME280 initialization and other small details. I’ve modified the code and now it should work.
I haven’t tested it, but I’m almost sure it will work. Can you test it?
Here’s the link: https://gist.github.com/sarasantos/5a2b8af769e65b84de03ede8ac024a84
If it is working well, now you can try to implement the receiver side. If you need, then I can help.
Answering your questions:
In all our examples, we use I2C to communicate with the BME280. The LoRa module uses SPI.
The GPIOs for the OLED display are not referenced in the code, because those are the default I2C pins of the ESP32. So, when you initialize the display, if you don’t reference any pins, it will use the default I2C pins.
The Web Server example, defines the pins, because those boards don’t use the default I2C pins.
I hope this helps.
Regards,
Sara
The new sender script is working fine, but on the receiver side it’s not looking so good. Much of the code is being ignored and the display shows the string with correct values but not formatted very nice. So if you could provide a cleaned up code I’ll be able to learn from it.
Also, in the sender code, what does this statement mean? I understand it’s part of OOP
Adafruit_BME280 bme
Hi Jack.
Can you show me your sender code? That way, I can see what might be wrong on the receiver side.
And can you share a picture on how your receiver is looking right now? You can share a picture using a link to Google Drive, dropbox or imgur, for example.
What statement are you talking about? I think you didn’t post the complete question.
Regards,
Sara
Hi Sara
The sender code is what you provided in your last response! ; )
An image of the receiver display can be seen from the link below. I am still trying to understand how to code for the display and any short tutorial would be appreciated, ie, the various command used, etc. Perhaps you know of a more detailed one I can refer to? (update: after writing this I found your tutorial at https://randomnerdtutorials.com/guide-for-oled-display-with-arduino/) – very nice.
https://drive.google.com/file/d/1rlyut5ZbqKZQDYJG2tFdNR1RYiYdbxGP/view?usp=sharing
The statement I am referring to is in the sender code.line 32 where an object is created. I am still getting familiar with OOP and when it is employed.
Adafruit_BME280 bme;
I see several lines further where the object is then performed on:
//BME280 setup
bool status = bme.begin(0x76);
if (!status) {
Serial.println(“Could not find a valid BME280 sensor, check wiring!”);
while (1);
}
} //End void setup
void getValues() {
Temperature = bme.readTemperature();
Pressure = bme.readPressure()/100.0F;
Altitude = bme.readAltitude(SEALEVELPRESSURE_HPA);
Humidity = bme.readHumidity();
}
Jack
Hi Jack.
We have a similar OLED tutorial for the ESP32: https://randomnerdtutorials.com/esp32-ssd1306-oled-display-arduino-ide/
Answering your second question.
Basically, Adafruit_BME280 is a class. A class is a blueprint for objects. It defines a set of attributes (data and functions) that characterize an object.
When you write Adafruit_BME280 bme; you are creating an object called bme. Then, when you can call methods defined inside that class to your object.
We have an explanation about classes and objects for MicroPython. The syntax is different, but the concepts are the same. You can read about it here: https://randomnerdtutorials.com/micropython-programming-basics-esp32-esp8266/, scroll down to Classes and Objects section.
I’ve noticed an error in the sender sketch I’ve sent you. I was using the same symbol (#) to separate humidity from pressure and pressure from altitude. The sketch is fixed now with a different symbol (%): https://gist.github.com/sarasantos/5a2b8af769e65b84de03ede8ac024a84
In your receiver sketch, it seems that the message is not split into its different components. Can you show me your code?
Regards,
Sara
Thanks Sara. The receiver code is listed in my initial question. But that brings up another interesting question: I wrote a second, modified version of the Receiver code. Although I don’t think I loaded it, how would I see what is currently loaded on the board?
Regarding “#” and “%”, I guess I don’t understand the meaning of those symbols. Why was that an error?
Jack
Hi Jack.
Your receiver code receives a message like this:
readingID/temperature&humidity#pressure%Altitude
For example: 1/27.43&65.40#1023.34%100
This means that you have the following:
- readingID = 1
- temperature = 27.43
- Humidity = 65.40
- Pressure = 1023.34
- Altitude = 100
We have all those different symbols so that we can split that message into its several readings. We’re using those symbols, but we could have used others.
For example, we know that before the / we have the reading ID, before the & we have the temperature and so on.
So, on the receiver side, we need to split that string. You’re not doing that in your receiver code.
You need to add something as follows to read the packet:
while (LoRa.available()) {
String LoRaData = LoRa.readString();
Serial.print(LoRaData);
int pos1 = LoRaData.indexOf('/');
int pos2 = LoRaData.indexOf('&');
int pos3 = LoRaData.indexOf('#');
int pos4 = LoRaData.indexOf('%');
readingID = LoRaData.substring(0, pos1);
temperature = LoRaData.substring(pos1 +1, pos2);
humidity= LoRaData.substring(pos2+1, pos3);
pressure = LoRaData.substring(pos3+1, pos4);
altitude= LoRaData.substring(pos4, LoRaData.length());
Now, you have the values saved on the right variables. So, you can use the methods to print to the OLED display.
display.clearDisplay();
display.setCursor(0,0);
display.print("Begin Sensor Data ");
//display.print(counter);
display.print("Temperature = ");
display.print(Temperature);
display.println(" *C");
display.setCursor(10,0)
display.print("Pressure = ");
display.print(Pressure);
display.println(" hPa");
display.setCursor(20,0);
display.print("Approx. Altitude = ");
display.print(Altitude);
display.println(" m");
display.setCursor(30,0);
display.print("Humidity = ");
display.print(Humidity);
display.println(" %");
display.println();
display.display();
Let me know if you’re able to modify your code with this.
Regards,
Sara
There are compilation errors. First message was “readingID” was not declared, so I added “#define readingID”.
The next error at line 89 :
“expected primary-expression before ‘=’ token
I noticed the variables were not capitalized so I changed that. But the same error occurs this time at line 93.
Also, I blocked out the rssi display section as I wasn’t sure if it was correct.
The current script is there
https://drive.google.com/file/d/1Ts5DNOy_FdEZPf1RhDGmd_zo36fM5NED/view?usp=sharing
Hi Jack.
You can’t define your variables as #define because you should use that for variables that won’t change.
In this case, define your variables as strings because we split the string message into other string variables:
String Temperature;
String Pressure;
String Humidity;
String Altitude;
String readingID;
Also, a semicolon was missing somewhere, but I added it now.
Here’s the code: https://gist.github.com/sarasantos/9835bac061a4e5d4992edb897614ca7f
See if it works now with the hardware. I’ve just compiled the code. I don’t have the hardware at hand to experiment with.
Regards,
Sara
It was still missing a semicolon, and fixed that. But there is still a display issue. Some images are below.
https://drive.google.com/file/d/1mLOdN2jIuaWxY9Eu5M8VcvrPqLFGRZTY/view?usp=sharing
https://drive.google.com/file/d/1Rn9nj4kNZsA5hJEpfaJbWxktrsemdp4A/view?usp=sharing
The current LoRa_Sender_BME.ino and LoRa_Receiver_BME.ino files are here:
https://drive.google.com/file/d/16Q_BIIx7VVrm06u4JZLimajUqEWRwSF_/view?usp=sharing
https://drive.google.com/file/d/1ZKQ8yFQh4kRaIKD3lJZqUAVodX8O-Pvu/view?usp=sharing
Hi.
I found out what is probably wrong now.
You’re using the coordinates of the OLED display wrong.
display.setCursor(x,y).
You are incrementing the x coordinate and not the y coordinate and it should be.
Experiment now the code: https://gist.github.com/sarasantos/9835bac061a4e5d4992edb897614ca7f
Regards,
Sara
Thanks Sara, unfortunately still not there. It just shows Altitude and Humidity, no readingID, Temperature or Pressure. THere is also a “%” before “Altitude” value, eg, “Altitude = %733.50 m”. I also removed “Approximate” as it caused word wrapping to the text below. Otherwise I tried to troubleshoot this but was unable to progress.
I’m not familiar with the use of “indexOf” or the “LoRaData.substring(x,posx)”.
Try it now: https://gist.github.com/sarasantos/9835bac061a4e5d4992edb897614ca7f
The indexOf gives us the position of the characters in a string: https://www.arduino.cc/reference/en/language/variables/data-types/string/functions/indexof
The substring functions cuts the string from x to y:
substring(x,y);
pos1 is the position of the first symbol
pos2 is the position of the second symbol.
So, substring(pos1+1, pos2); gives us the value that goes between those symbols.
(we add 1 because the value we want comes after the symbol)
https://www.arduino.cc/reference/en/language/variables/data-types/string/functions/substring
I hope this is clear.
Regards,
Sara
Perfect !
https://drive.google.com/file/d/1LWv03qM15g_cUK_fIglaPyRWs75Vtd8i/view?usp=sharing
Could you help me understand what changes you made? What prevented the other values to display, and why was there a “%” before the Altitude value? What are
display.cp437(true);
display.write(167);
Sara, I appreciate all your help making this work and I hope others will find this small project to learn from.
I want to also log the data as described in Project 4. How would I do that on the same board with a display? They would both be using the same GPIO pins.
Jack
Great!
The other values weren’t being displayed because we forgot to add the code to display those values.
The % was being displayed because I forget to add 1 to split that string. I was using:
Altitude = LoRaData.substring(pos4, LoRaData.length());
Instead of
Altitude = LoRaData.substring(pos4+1, LoRaData.length());
To display the º symbol, we use the Code Page 437 font. For that, you need to set the cp437 to true as follows:
display.cp437(true);
Then, use the write() method to display your chosen character. The º symbol corresponds to character 167.
display.write(167);
Answering your final question. They use different GPIOs. The microSD card uses SPI communication protocol and the OLED uses I2C. Even if both used I2C, you could use them both on the same pins. Learn more about I2C with the ESP32 here: https://randomnerdtutorials.com/esp32-i2c-communication-arduino-ide/
I hope this helps.
Regards,
Sara