#include <Arduino.h>
#include <SPI.h>
#include <RadioLib.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <OneWire.h>
#include <DallasTemperature.h>
// ================== LoRa pins (your working T3-S3 V1.2 setup)
==================
#define LORA_SCK 5
#define LORA_MISO 3
#define LORA_MOSI 6
#define LORA_CS 7
#define LORA_DIO1 33
#define LORA_RST 8
#define LORA_BUSY 34
SPIClass loraSPI(FSPI);
SPISettings loraSettings(2000000, MSBFIRST, SPI_MODE0);
SX1262 radio = new Module(LORA_CS, LORA_DIO1, LORA_RST, LORA_BUSY,
loraSPI, loraSettings);
// ================== DS18B20 ==================
#define ONE_WIRE_PIN 41
OneWire oneWire(ONE_WIRE_PIN);
DallasTemperature sensors(&oneWire);
// ================== OLED (common LilyGO I2C OLED setup)
==================
#define OLED_SDA 18
#define OLED_SCL 17
#define OLED_ADDR 0x3C
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire,
-1);
// ================== App ==================
static const char* CMD_TEMP = "INCUBt0000";
static const char* ID_TEMP = "INCUB";
// the ID field you asked for
float lastTempC = NAN;
unsigned long lastDisplayMs = 0;
const unsigned long DISPLAY_PERIOD_MS = 10000;
static void drawTempLarge(float tC) {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
// Big temperature
display.setTextSize(3); // "large font" on 128x64
String line;
if (isnan(tC)) {
line = "--.-C";
} else {
line = String(tC, 1) + "C";
}
// Center it roughly
int16_t x1, y1;
uint16_t w, h;
display.getTextBounds(line, 0, 0, &x1, &y1, &w,
&h);
int16_t x = (SCREEN_WIDTH - (int16_t)w) / 2;
int16_t y = (SCREEN_HEIGHT - (int16_t)h) / 2;
display.setCursor(x, y);
display.print(line);
// Small label at bottom
display.setTextSize(1);
display.setCursor(0, 56);
display.print("Listening...");
display.display();
}
static float readTempC() {
sensors.requestTemperatures();
// blocking ~ up to 750ms at 12-bit
float t = sensors.getTempCByIndex(0);
if (t == DEVICE_DISCONNECTED_C) return NAN;
return t;
}
void setup() {
Serial.begin(115200);
delay(200);
Serial.println("Booted");
// OLED init
Wire.begin(OLED_SDA, OLED_SCL);
if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
Serial.println("OLED init failed (check I2C
addr/pins).");
} else {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("INCUB Temp Node");
display.display();
}
// DS18B20 init
sensors.begin();
// LoRa init
loraSPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
int state = radio.begin();
if (state != RADIOLIB_ERR_NONE) {
Serial.print("radio.begin() failed, code=");
Serial.println(state);
while (true) delay(1000);
}
// Match your network / receiver settings
radio.setFrequency(868.0);
radio.setBandwidth(125.0);
radio.setSpreadingFactor(9);
radio.setCodingRate(5); //
4/5
radio.setPreambleLength(8);
radio.setSyncWord(0x34);
radio.setOutputPower(17);
radio.setCRC(true);
// keep consistent with your other nodes
Serial.println("Radio configured. Listening...");
// First reading + display
lastTempC = readTempC();
drawTempLarge(lastTempC);
lastDisplayMs = millis();
}
void loop() {
// Update temperature + OLED every 10 seconds
unsigned long now = millis();
if (now - lastDisplayMs >= DISPLAY_PERIOD_MS) {
lastTempC = readTempC();
Serial.print("TempC: ");
Serial.println(lastTempC, 2);
if (display.width() > 0)
drawTempLarge(lastTempC);
lastDisplayMs = now;
}
// Listen for command
String rx;
int state = radio.receive(rx);
if (state == RADIOLIB_ERR_NONE) {
rx.trim();
Serial.print("RX: '");
Serial.print(rx);
Serial.println("'");
if (rx == CMD_TEMP) {
// Build: ID,temperature,nan,nan,nan
// Use the most recent reading (or
take a fresh one if you prefer)
float t = lastTempC;
if (isnan(t)) t = readTempC();
String out = String(ID_TEMP) + "," +
String(t, 2) + ",nan,nan,nan";
Serial.print("TX: ");
Serial.println(out);
int txState = radio.transmit(out);
if (txState == RADIOLIB_ERR_NONE) {
Serial.println("TX OK");
} else {
Serial.print("TX failed,
code=");
Serial.println(txState);
}
}
} else if (state != RADIOLIB_ERR_RX_TIMEOUT) {
Serial.print("RX error, code=");
Serial.println(state);
}
delay(10);
}