#include <SoftwareSerial.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// OLED Display Settings (0.96 inch, 128x64 resolution)
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C // Common I2C address for 0.96" OLED (try 0x3D if it doesn't work)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// SoftwareSerial Pins for AJ-SR04M Mode 4
#define RX_PIN 16 // Connects to Sensor TX
#define TX_PIN 17 // Connects to Sensor RX
SoftwareSerial mySerial(RX_PIN, TX_PIN);
byte packet[4];
int packetIndex = 0;
unsigned long lastByteTime = 0;
unsigned long lastTriggerTime = 0;
const unsigned long triggerInterval = 100; // Trigger every 1 second for Low-Power Mode 4
void setup() {
Serial.begin(115200);
mySerial.begin(9600);
// Initialize I2C and OLED Display
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed!"));
for(;;); // Don't proceed, loop forever
}
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(1);
display.setCursor(0, 10);
display.println("AJ-SR04M Mode 4");
display.setCursor(0, 30);
display.println("Initializing...");
display.display();
delay(1500);
Serial.println("AJ-SR04M Mode 4 (47k ohm) & OLED Initialized");
}
void loop() {
// Step 1: Send trigger byte 0x01 periodically (non-blocking)
if (millis() - lastTriggerTime >= triggerInterval) {
lastTriggerTime = millis();
mySerial.write(0x01);
}
// Step 2: Non-blocking state-machine to read incoming response bytes
while (mySerial.available() > 0) {
byte incomingByte = mySerial.read();
// If there is a pause longer than 100ms, reset the packet index to re-sync
if (millis() - lastByteTime > 100) {
packetIndex = 0;
}
lastByteTime = millis();
// Look for the 0xFF header
if (packetIndex == 0) {
if (incomingByte == 0xFF) {
packet[0] = incomingByte;
packetIndex = 1;
}
}
// Collect the remaining 3 bytes
else {
packet[packetIndex] = incomingByte;
packetIndex++;
// Once we have a full 4-byte packet
if (packetIndex == 4) {
byte d1 = packet[1];
byte d2 = packet[2];
byte checksum = packet[3];
byte calculatedChecksum = d1 + d2;
// Validate checksum with the module's offset tolerance
if (checksum == calculatedChecksum || checksum == (calculatedChecksum - 1)) {
int distance_mm = (d1 << 8) + d2;
int distance_cm = distance_mm / 10;
// Print to Serial Monitor
Serial.print("Distance: ");
Serial.print(distance_cm);
Serial.println(" cm");
// Update OLED Display
display.clearDisplay();
// Title
display.setTextSize(1);
display.setCursor(0, 0);
display.print("AJ-SR04M Distance");
// Line separator
display.drawLine(0, 12, 128, 12, SSD1306_WHITE);
// Distance Value in Large Text
display.setTextSize(2);
display.setCursor(10, 28);
display.print(distance_cm);
display.setTextSize(1);
display.print(" cm");
display.display();
}
// Reset index to look for the next packet header
packetIndex = 0;
}
}
}
}
Comments
Post a Comment