Vastaanottimen lähdekoodi V2: Difference between revisions
From Pessin randon wiki
Created page with "=== Versiohistoria === ==== V2.0 ==== Muutettu täysin näytön näyttötapaa. Parannettu vastaanotetun tiedon varmistamista käyttäen CRC-16 funktiota. Tiedetyt ongelmat. Rekisteröi uuden vastaanotetun koodin vasta kun näyttö on piirtänyt KAIKKI ID:t.<syntaxhighlight lang="c#"> #include <SPI.h> #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #include <RH_ASK.h> #include <CRC16.h> #define OLED_RESET -1 #define SCREEN_WIDTH 128 // OLED d..." |
|||
| Line 68: | Line 68: | ||
void loop() { | void loop() { | ||
handleRadioReceiver(); //receive packages | handleRadioReceiver(); //receive packages | ||
| Line 139: | Line 138: | ||
} | } | ||
/* | |||
bool checkChecksum(uint8_t *data, uint8_t *receivedCrc) { | bool checkChecksum(uint8_t *data, uint8_t *receivedCrc) { | ||
CRC16 crc; | CRC16 crc; | ||
| Line 146: | Line 145: | ||
uint16_t calcCrc = crc.calc(); | uint16_t calcCrc = crc.calc(); | ||
return (calcCrc == *(uint16_t *)receivedCrc); | return (calcCrc == *(uint16_t *)receivedCrc); | ||
} | }*/ | ||
uint8_t processPacket(uint8_t *data, uint8_t dataLength) { | uint8_t processPacket(uint8_t *data, uint8_t dataLength) { | ||
Revision as of 17:44, 3 October 2025
Versiohistoria
V2.0
Muutettu täysin näytön näyttötapaa.
Parannettu vastaanotetun tiedon varmistamista käyttäen CRC-16 funktiota.
Tiedetyt ongelmat. Rekisteröi uuden vastaanotetun koodin vasta kun näyttö on piirtänyt KAIKKI ID:t.
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <RH_ASK.h>
#include <CRC16.h>
#define OLED_RESET -1
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
RH_ASK driver(1000, 12, 11, 10); // RX = D12
//ID:n tallennusmuuttujat
const int MAX_IDS = 16;
uint8_t ids[MAX_IDS];
unsigned long idTimes[MAX_IDS]; //Aikaleima
int numIds = 0;
//Screen indicator
const unsigned long BLINK_INTERVAL = 500;
bool indicatorOn = false;
unsigned long indicatorTime = 0;
// ID activity & deactivity
//const unsigned long ACTIVE_TIME = 300000; // time threshold for active IDs (5 minutes)
const unsigned long INACTIVE_TIME = 3600000; // time threshold for inactive IDs (1 hour)
// Screen rotation time
const unsigned long DISPLAY_DURATION = 2500; // 2.5 s
int selectedId = 0;
unsigned long lastSelectedTime = 0;
void setup() {
Serial.begin(9600);
// initialize the OLED screen
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(2);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println(F("Odotetaan..."));
display.display();
if (!driver.init()) {
display.clearDisplay();
display.setCursor(0, 0);
display.println(F("Radio ei vastaa"));
display.display();
while (1); //
}
}
void loop() {
handleRadioReceiver(); //receive packages
// update the selected ID every 3 seconds to show different ID's timestamp
if (millis() - lastSelectedTime >= DISPLAY_DURATION) {
selectedId = (selectedId + 1) % numIds;
lastSelectedTime = millis();
displayData();
}
//displayData(); // display all of the received IDs and their last seen times, or "Waiting for message..." if there are no IDs recorded
removeInactiveIds(); // remove any inactive IDs older than INACTIVE_TIME
}
//Receive the radio message
void handleRadioReceiver() {
uint8_t buf[RH_ASK_MAX_MESSAGE_LEN];
uint8_t buflen = sizeof(buf);
static bool checksumReceived = false;
static uint16_t receivedChecksum;
uint16_t checksumValue;
uint8_t data[4];
if (driver.recv(buf, &buflen)) { // Non-blocking
int16_t rssi = driver.lastRssi();
if (buflen == 2 && !checksumReceived) {
// Received checksum packet
receivedChecksum = *(uint16_t *)buf;
checksumReceived = true;
} else if (buflen == 4 && checksumReceived) {
// Received data packet, with preceding valid checksum packet
memcpy(data, buf, sizeof(data));
CRC16 crc;
crc.add(data, sizeof(data)); // add the DIP switch values to the CRC calculation
checksumValue = crc.calc();
if(checksumValue == receivedChecksum) {
uint8_t id = processPacket(data, sizeof(data) / sizeof(data[0]));
// Check if ID value is valid
if (id >= 0 && id < MAX_IDS) {
bool found = false;
for (int i = 0; i < numIds; i++) {
if (ids[i] == id) {
found = true;
idTimes[i] = millis(); // Update the last time this ID was received
break;
}
}
if (!found && numIds < MAX_IDS) {
ids[numIds] = id;
idTimes[numIds] = millis();
numIds++;
}
}
checksumReceived = false;
} else {
checksumReceived = false;
}
} else {
// Invalid packet length or out-of-order transmission
checksumReceived = false;
}
}
}
/*
bool checkChecksum(uint8_t *data, uint8_t *receivedCrc) {
CRC16 crc;
crc.setPolynome(0x1021); // CCITT polynomial (0x1021)
crc.add(data, sizeof(data));
uint16_t calcCrc = crc.calc();
return (calcCrc == *(uint16_t *)receivedCrc);
}*/
uint8_t processPacket(uint8_t *data, uint8_t dataLength) {
uint8_t id = 0;
for (uint8_t i = 0; i < dataLength; i++) {
id |= data[i] << i; // convert DIP code to ID
}
return id;
}
void displayData() {
display.clearDisplay();
if (numIds == 0) {
display.setCursor(0, 10);
display.println("Waiting for");
display.print("message...");
} else {
// Valitaan fonttikoko ID-määrän perusteella
int textSize;
int idsPerRow = 4;
if (numIds < 4) {
textSize = 3;
} else if (numIds < 8) {
textSize = 2;
} else {
textSize = 1;
idsPerRow = 6;
}
display.setTextSize(textSize);
// Perustiedot
//const int charsPerId = 2; // max 2 merkkiä ID:ssä
//const int charWidth = 6; // per merkki (fontti size=1)
//const int idBoxWidth = charsPerId * charWidth * textSize + 2; // pieni väli
const int idBoxWidth = 15 * textSize;
//int idsPerRow = (textSize == 1) ? 8 : 4; // size=1 → 8 per rivi, muuten 4
int rowHeight = 8 * textSize;
// Piirretään ID:t riveittäin
for (int i = 0; i < numIds; i++) {
int row = i / idsPerRow;
int col = i % idsPerRow;
int x = col * idBoxWidth;
int y = row * rowHeight;
if (i == selectedId) {
display.setTextColor(BLACK, WHITE); // invertoitu
} else {
display.setTextColor(WHITE, BLACK);
}
display.setCursor(x, y);
display.print(ids[i]);
}
// Last seen aika
display.setTextSize(1);
display.setTextColor(WHITE);
int lastSeenMins = (millis() - idTimes[selectedId]) / 60000;
display.setCursor(SCREEN_WIDTH - 24, SCREEN_HEIGHT - 8);
display.print(lastSeenMins);
display.print("m");
}
// Vilkkuva indikaattori
//if (millis() - indicatorTime >= BLINK_INTERVAL) {
indicatorOn = !indicatorOn;
indicatorTime = millis();
display.setCursor(0, SCREEN_HEIGHT - 8);
if (indicatorOn) {
display.print(".");
} else {
display.print(" ");
}
//}
display.display();
}
void removeInactiveIds() {
for (int i = numIds - 1; i >= 0; i--) {
if (millis() - idTimes[i] > INACTIVE_TIME) {
// shift the remaining IDs and last seen times down by one position to overwrite the inactive ID
for (int j = i + 1; j < numIds; j++) {
ids[j - 1] = ids[j];
idTimes[j - 1] = idTimes[j];
}
numIds--;
}
}
}