more rp2040 stuff

This commit is contained in:
2026-04-04 01:10:19 -03:00
parent b2bc0801f5
commit 7f4b23efda
20 changed files with 594 additions and 184 deletions

View File

@@ -0,0 +1,18 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:waveshare_rp2040_zero]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
board = waveshare_rp2040_zero
framework = arduino
monitor_speed = 115200
lib_deps =
https://github.com/Chris--A/Keypad
bogde/HX711@^0.7.5

View File

@@ -0,0 +1,84 @@
#include <Arduino.h>
#include "HX711.h"
const int LOADCELL_DOUT_PIN = 2;
const int LOADCELL_SCK_PIN = 3;
HX711 scale;
float smoothedWeight = 0.0;
float alpha = 0.3;
float calibration_factor = 111.17;
float known_weight = 796.0;
// Stability Lock Variables
float lastDisplayedWeight = 0.0;
const float STABILITY_THRESHOLD = 0.5;
void calibrateScale() {
Serial.println("--- Calibration Mode ---");
Serial.println("1. Clear scale, type 't' to tare.");
Serial.print("2. Place "); Serial.print(known_weight); Serial.println("g weight.");
Serial.println("3. Type 'c' to confirm weight.");
while (true) {
if (Serial.available()) {
char c = Serial.read();
if (c == 't') {
scale.tare();
Serial.println("Tared! Place weight and type 'c'...");
} else if (c == 'c') {
long reading = scale.get_value(15);
calibration_factor = (float)reading / known_weight;
scale.set_scale(calibration_factor);
Serial.print("New Factor: "); Serial.println(calibration_factor);
Serial.println("Calibration Done! Exiting mode.");
break;
}
}
}
}
void setup() {
Serial.begin(115200);
scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
scale.set_gain(128);
scale.set_scale(calibration_factor);
scale.tare();
Serial.println("HX711 Ready (Stable Lock Mode)");
}
void loop() {
if (scale.is_ready()) {
float currentReading = scale.get_units(1);
smoothedWeight = (alpha * currentReading) + (1.0 - alpha) * smoothedWeight;
// 1. Calculate the intended new display value
float targetWeight = round(smoothedWeight * 2.0) / 2.0;
if (abs(targetWeight) < 1.0) targetWeight = 0.0;
// 2. Stability Check
// Only update lastDisplayedWeight if the change exceeds the threshold
if (abs(targetWeight - lastDisplayedWeight) >= STABILITY_THRESHOLD) {
lastDisplayedWeight = targetWeight;
}
Serial.print("Weight: ");
Serial.print(lastDisplayedWeight, 1);
Serial.println(" g");
}
if (Serial.available()) {
char cmd = Serial.read();
if (cmd == 't') {
scale.tare();
smoothedWeight = 0;
lastDisplayedWeight = 0; // Force display to zero immediately
Serial.println(">> Tared");
} else if (cmd == 'k') {
calibrateScale();
}
}
delay(10);
}

View File

@@ -1,112 +0,0 @@
#include <Arduino.h>
const int SCLK_PIN = 1;
const int DOUT_PIN = 2;
long tareOffset = 0;
float calibrationFactor = 74.17; //1.0 by default, callibrated by placing 796 weight and callibrating
float smoothedWeight = 0.0;
float alpha = 0.15; // Adjustment: 0.05 (very smooth/slow) to 0.3 (jumpy/fast)
long readSD10809() {
long data = 0;
// Wait for DRDY to go LOW
uint32_t timeout = millis();
while (digitalRead(DOUT_PIN) == HIGH) {
if (millis() - timeout > 100) return -1; // 20Hz rate is 50ms
}
// Read 24-bit ADC result [cite: 158, 160]
for (int i = 0; i < 24; i++) {
digitalWrite(SCLK_PIN, HIGH);
delayMicroseconds(1);
data = (data << 1) | digitalRead(DOUT_PIN);
digitalWrite(SCLK_PIN, LOW);
delayMicroseconds(1);
}
// Send 3 extra pulses (Total 27) to keep Channel A at 128x Gain [cite: 152, 161]
for (int i = 0; i < 3; i++) {
digitalWrite(SCLK_PIN, HIGH);
delayMicroseconds(1);
digitalWrite(SCLK_PIN, LOW);
delayMicroseconds(1);
}
// Handle 24-bit Two's Complement sign extension [cite: 108]
if (data & 0x800000) data |= 0xFF000000;
return data;
}
long getAverageReading(int samples) {
long sum = 0;
int count = 0;
while (count < samples) {
long val = readSD10809();
if (val != -1) {
sum += val;
count++;
}
}
return sum / samples;
}
void tare() {
Serial.println("Taring... keep scale still.");
tareOffset = getAverageReading(20);
Serial.print("New Offset: ");
Serial.println(tareOffset);
}
void calibrate(float knownWeightGrams) {
long currentRaw = getAverageReading(20);
calibrationFactor = (float)(currentRaw - tareOffset) / knownWeightGrams;
Serial.print("Calibration Factor set to: ");
Serial.println(calibrationFactor);
}
void setup() {
Serial.begin(115200);
pinMode(SCLK_PIN, OUTPUT);
pinMode(DOUT_PIN, INPUT);
// Give the chip time to stabilize (2 cycles for SD10809) [cite: 142]
delay(500);
tare();
}
void loop() {
long raw = readSD10809();
if (raw != -1) {
// 1. Calculate current instantaneous weight
float currentWeight = (raw - tareOffset) / calibrationFactor;
// 2. Apply EMA Filter
smoothedWeight = (alpha * currentWeight) + (1.0 - alpha) * smoothedWeight;
// 3. Optional: "Auto-Zero" or Snap-to-Zero
// If the weight is within 0.05g of zero, just show 0.00
float displayWeight = smoothedWeight;
if (abs(displayWeight) < 0.05) {
displayWeight = 0.00;
}
Serial.print("Weight: ");
Serial.print(displayWeight, 2);
Serial.println(" g");
}
// Example trigger for calibration via Serial
if (Serial.available()) {
char c = Serial.read();
if (c == 't') {
tare();
}
if (c == 'c') {
calibrate(796);
}
}
}

View File

@@ -0,0 +1,5 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch

View File

@@ -0,0 +1,10 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
],
"unwantedRecommendations": [
"ms-vscode.cpptools-extension-pack"
]
}

View File

@@ -0,0 +1,37 @@
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the convention is to give header files names that end with `.h'.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html

View File

@@ -0,0 +1,46 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into the executable file.
The source code of each library should be placed in a separate directory
("lib/your_library_name/[Code]").
For example, see the structure of the following example libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional. for custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
Example contents of `src/main.c` using Foo and Bar:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
The PlatformIO Library Dependency Finder will find automatically dependent
libraries by scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html

View File

@@ -13,3 +13,4 @@ platform = https://github.com/maxgerhardt/platform-raspberrypi.git
board = waveshare_rp2040_zero
framework = arduino
monitor_speed = 115200
lib_deps = https://github.com/Chris--A/Keypad

View File

@@ -0,0 +1,50 @@
#ifndef TM1621_CONFIG_H
#define TM1621_CONFIG_H
#include <Arduino.h>
const uint8_t digitMap[] = {
0b11111100, // 0
0b00000110, // 1
0b01011011, // 2
0b01001111, // 3
0b01100110, // 4
0b01101101, // 5
0b01111101, // 6
0b00000111, // 7
0b01111111, // 8
0b01101111 // 9
};
const int arrows[] = {283,363,183,203}; //tare,?,?,Zero
const int battery[] = {63,83,103}; //LOW / MED / FULL
// Following your pattern: {A, B, C, D, E, F, G}
const int row1_d1[] = {300, 301, 302, 313, 312, 310, 311}; // Addresses 30 & 31
const int row1_d2[] = {280, 281, 282, 293, 292, 290, 291}; // Addresses 28 & 29
const int row1_d3[] = {260, 261, 262, 273, 272, 270, 271}; // Addresses 26 & 27
const int row1_d4[] = {240, 241, 242, 253, 252, 250, 251}; // Addresses 24 & 25
const int row1_d5[] = {220, 221, 222, 233, 232, 230, 231}; // Addresses 22 & 23
const int row1_decimal[] = {263,232,223}; //XX.X.X.X
const int row2_d1[] = {200, 201, 202, 213, 212, 210, 211}; // Addresses 20 & 21
const int row2_d2[] = {180, 181, 182, 193, 192, 190, 191}; // Addresses 18 & 19
const int row2_d3[] = {160, 161, 162, 173, 172, 170, 171}; // Addresses 16 & 17
const int row2_d4[] = {140, 141, 142, 153, 152, 150, 151}; // Addresses 14 & 15
const int row2_d5[] = {120, 121, 122, 133, 132, 130, 131}; // Addresses 12 & 13
const int row2_decimal[] = {163,143,123}; //XX.X.X.X
const int row3_d1[] = {100, 101, 102, 113, 112, 110, 111}; // Addresses 10 & 11
const int row3_d2[] = {80, 81, 82, 93, 92, 90, 91}; // Addresses 8 & 9
const int row3_d3[] = {60, 61, 62, 73, 72, 70, 71}; // Addresses 6 & 7
const int row3_d4[] = {40, 41, 42, 53, 52, 50, 51}; // Addresses 4 & 5
const int row3_d5[] = {20, 21, 22, 33, 32, 30, 31}; // Addresses 2 & 3
const int row3_d6[] = {0, 1, 2, 13, 12, 10, 11}; // Addresses 0 & 1
const int row3_decimal[] = {43,23,3}; //XX.X.X.X
const int* digitsRow1[] = {row1_d1, row1_d2, row1_d3, row1_d4, row1_d5};
const int* digitsRow2[] = {row2_d1, row2_d2, row2_d3, row2_d4, row2_d5};
const int* digitsRow3[] = {row3_d1, row3_d2, row3_d3, row3_d4, row3_d5, row3_d6};
const int* decimals[] = {row1_decimal, row2_decimal, row3_decimal};
#endif

View File

@@ -0,0 +1,270 @@
#include <Arduino.h>
#include "TM1621_Config.h"
#include <Keypad.h>
#define SCLK_SDI0819 1
#define DOUT_SDI0819 2
#define LCD_DATA 3
#define LCD_WR 4
#define LCD_CS 5
#define BUZZER_PIN 6
#define BACKLIGHT_PIN 7
int currentAddr = 0;
int currentBit = 0;
void writeBits(uint32_t data, uint8_t count) {
for (int8_t i = count - 1; i >= 0; i--) {
digitalWrite(LCD_WR, LOW);
digitalWrite(LCD_DATA, (data >> i) & 0x01);
digitalWrite(LCD_WR, HIGH);
}
}
void sendCmd(uint8_t cmd) {
digitalWrite(LCD_CS, LOW);
writeBits(0x04, 3); // Binary 100 [cite: 432]
writeBits(cmd, 8); // Command [cite: 413, 534]
writeBits(0, 1); // X bit [cite: 416]
digitalWrite(LCD_CS, HIGH);
}
void writeAddr(uint8_t addr, uint8_t data) {
digitalWrite(LCD_CS, LOW);
uint16_t header = (0x05 << 6) | (addr & 0x3F); // Mode 101 [cite: 475]
writeBits(header, 9);
writeBits(data & 0x0F, 4); // 4 bits of data [cite: 475]
digitalWrite(LCD_CS, HIGH);
}
void updateDisplay() {
// Clear all segments first
for (int i = 0; i < 32; i++) {
writeAddr(i, 0x00);
}
// Light up only the current bit
writeAddr(currentAddr, (1 << currentBit));
Serial.print(">>> CURRENT - Address: ");
Serial.print(currentAddr);
Serial.print(" | Bit (COM): ");
Serial.println(currentBit);
Serial.println("Enter 'n' for Next, 'p' for Prev:");
}
uint8_t shadowRAM[32] = {0};
void writeMappedSegment(int aab, bool state) {
int addr = aab / 10;
int bit = aab % 10;
if (state) shadowRAM[addr] |= (1 << bit);
else shadowRAM[addr] &= ~(1 << bit);
writeAddr(addr, shadowRAM[addr]);
}
void displayDigit(const int segments[], int number) {
uint8_t bits = digitMap[number % 10];
for (int i = 0; i < 7; i++) {
// We check Bit 0, then Bit 1, etc.
// This maps i=0 to Segment A, i=1 to Segment B...
bool state = (bits >> i) & 0x01;
writeMappedSegment(segments[i], state);
}
}
void printToRow(int row, long value, int decimalPos = 0) {
const int** currentRow;
int numDigits;
// Select row configuration
switch(row) {
case 1: currentRow = digitsRow1; numDigits = 5; break;
case 2: currentRow = digitsRow2; numDigits = 5; break;
case 3: currentRow = digitsRow3; numDigits = 6; break;
default: return;
}
// Display the number right-aligned
long tempValue = value;
for (int i = numDigits - 1; i >= 0; i--) {
if (tempValue > 0 || i == numDigits - 1) { // Show at least one digit
displayDigit(currentRow[i], tempValue % 10);
tempValue /= 10;
} else {
// Clear leading zeros (all segments off)
for (int s = 0; s < 7; s++) writeMappedSegment(currentRow[i][s], false);
}
}
// Handle Decimal Points (if applicable for that row)
if (decimalPos > 0 && decimalPos <= 3) {
writeMappedSegment(decimals[row-1][decimalPos-1], true);
}
}
void setupDisplay() {
pinMode(LCD_DATA, OUTPUT);
pinMode(LCD_WR, OUTPUT);
pinMode(LCD_CS, OUTPUT);
digitalWrite(LCD_CS, HIGH); // Initialize serial interface [cite: 443]
sendCmd(0x01); // SYS EN [cite: 534]
sendCmd(0x29); // BIAS 1/3, 4 COM [cite: 420, 544]
sendCmd(0x03); // LCD ON [cite: 534]
updateDisplay();
}
const byte ROWS = 4;
const byte COLS = 5;
char keys[ROWS][COLS] = {{'1', '2', '3', 'C', 'T'},
{'4', '5', '6', 'A', 'Z'},
{'7', '8', '9', 'X', 'Y'},
{'0', '.', 'S', 'M', 'L'}};
byte rowPins[ROWS] = {8,9, 10, 11};
byte colPins[COLS] = {12,13,14,15,16};
Keypad kpd = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
void playBeep() {
analogWrite(BUZZER_PIN, 10);
delay(50);
analogWrite(BUZZER_PIN, 0);
}
long tareOffset = 0;
float calibrationFactor =
74.17; // 1.0 by default, callibrated by placing 796 weight and callibrating
long readSD10809() {
long data = 0;
// Wait for DRDY to go LOW
uint32_t timeout = millis();
while (digitalRead(DOUT_SDI0819) == HIGH) {
if (millis() - timeout > 100)
return -1; // 20Hz rate is 50ms
}
// Read 24-bit ADC result [cite: 158, 160]
for (int i = 0; i < 24; i++) {
digitalWrite(SCLK_SDI0819, HIGH);
delayMicroseconds(1);
data = (data << 1) | digitalRead(DOUT_SDI0819);
digitalWrite(SCLK_SDI0819, LOW);
delayMicroseconds(1);
}
// Send 3 extra pulses (Total 27) to keep Channel A at 128x Gain [cite: 152,
// 161]
for (int i = 0; i < 3; i++) {
digitalWrite(SCLK_SDI0819, HIGH);
delayMicroseconds(1);
digitalWrite(SCLK_SDI0819, LOW);
delayMicroseconds(1);
}
// Handle 24-bit Two's Complement sign extension [cite: 108]
if (data & 0x800000)
data |= 0xFF000000;
return data;
}
long getAverageReading(int samples) {
long sum = 0;
int count = 0;
while (count < samples) {
long val = readSD10809();
if (val != -1) {
sum += val;
count++;
}
}
return sum / samples;
}
void tare() {
Serial.println("Taring... keep scale still.");
tareOffset = getAverageReading(20);
Serial.print("New Offset: ");
Serial.println(tareOffset);
}
void calibrate(float knownWeightGrams) {
long currentRaw = getAverageReading(20);
calibrationFactor = (float)(currentRaw - tareOffset) / knownWeightGrams;
Serial.print("Calibration Factor set to: ");
Serial.println(calibrationFactor);
}
void setupADC() {
pinMode(SCLK_SDI0819, OUTPUT);
pinMode(DOUT_SDI0819, INPUT);
// Give the chip time to stabilize (2 cycles for SD10809) [cite: 142]
delay(500);
tare();
}
void setup() {
Serial.begin(115200);
setupDisplay();
setupADC();
}
void loop() {
long raw = readSD10809();
if (kpd.getKeys()) {
for (int i = 0; i < LIST_MAX; i++) {
if (kpd.key[i].stateChanged) {
String msg = "";
switch (kpd.key[i].kstate) {
case PRESSED:
msg = " PRESSED.";
playBeep();
break;
case HOLD:
msg = " HOLD.";
break;
case RELEASED:
msg = " RELEASED.";
break;
case IDLE:
msg = " IDLE.";
break;
}
if (msg != "") {
Serial.print("Key ");
Serial.print(kpd.key[i].kchar);
Serial.println(msg);
}
}
}
}
if (raw != -1) {
float displayWeight = (raw - tareOffset) / calibrationFactor;
Serial.print("Weight: ");
Serial.print(displayWeight, 2);
Serial.println(" g");
}
// Example trigger for calibration via Serial
if (Serial.available()) {
char c = Serial.read();
if (c == 't') {
tare();
}
if (c == 'c') {
calibrate(796);
}
}
}

View File

@@ -0,0 +1,11 @@
This directory is intended for PlatformIO Test Runner and project tests.
Unit Testing is a software testing method by which individual units of
source code, sets of one or more MCU program modules together with associated
control data, usage procedures, and operating procedures, are tested to
determine whether they are fit for use. Unit testing finds problems early
in the development cycle.
More information about PlatformIO Unit Testing:
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html

Binary file not shown.

View File

@@ -54,11 +54,6 @@ void setup() {
pinMode(LCD_CS, OUTPUT);
digitalWrite(LCD_CS, HIGH); // Initialize serial interface [cite: 443]
Serial.begin(9600);
// while (!Serial);
Serial.println("--- TM1621 Interactive Mapper ---");
sendCmd(0x01); // SYS EN [cite: 534]
sendCmd(0x29); // BIAS 1/3, 4 COM [cite: 420, 544]
sendCmd(0x03); // LCD ON [cite: 534]

View File

@@ -13,3 +13,4 @@ platform = https://github.com/maxgerhardt/platform-raspberrypi.git
board = waveshare_rp2040_zero
framework = arduino
monitor_speed = 115200
lib_deps = https://github.com/Chris--A/Keypad

View File

@@ -1,76 +1,70 @@
#include <Arduino.h>
#include <Keypad.h>
const int BUZZER_PIN = 6;
const int pins[] = {0, 1, 2, 3, 4, 5, 7};
const int numPins = 7;
#define BUZZER_PIN 9
struct KeyMap {
int strobe;
int target;
char key;
};
const byte ROWS = 4;
const byte COLS = 5;
// Your discovered mapping
KeyMap keypad[] = {{7, 1, '1'}, {7, 2, '2'}, {3, 7, '3'}, {5, 0, 'C'},
{7, 0, 'T'}, {4, 1, 'm'}, {1, 2, 'Y'}, {5, 3, '6'},
{1, 0, '+'}, {2, 0, 'Z'}, {1, 5, '7'}, {5, 2, 'U'},
{2, 5, '8'}, {3, 5, '9'}, {2, 4, 'M'}, {3, 1, '4'},
{0, 2, '5'}, {3, 4, 'P'}, {4, 0, '$'}, {0, 4, 'L'}};
char keys[ROWS][COLS] = {{'1', '2','3','C','T'},
{'4', '5','6','A','Z'},
{'7', '8','9','X','Y'},
{'0', '.','S','M','L'}};
void setup() {
Serial.begin(115200);
for (int p : pins) {
pinMode(p, INPUT_PULLUP);
}
// Keep buzzer pin high-impedance so it doesn't sink the matrix
pinMode(BUZZER_PIN, INPUT_PULLUP);
}
byte rowPins[ROWS] = {0,1,2,3};
byte colPins[COLS] = {4,5,6,7,8};
Keypad kpd = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
unsigned long loopCount = 0;
unsigned long startTime;
void playBeep() {
analogWrite(BUZZER_PIN, 10);
delay(50); // Beep duration
analogWrite(BUZZER_PIN, 0); // Turn it off
pinMode(BUZZER_PIN, INPUT_PULLUP); // Reset to input for the matrix
delay(50);
analogWrite(BUZZER_PIN, 0);
}
char getKeyPressed() {
for (int s = 0; s < numPins; s++) {
int strobe = pins[s];
pinMode(strobe, OUTPUT);
digitalWrite(strobe, LOW);
delayMicroseconds(50);
for (int i = 0; i < numPins; i++) {
int target = pins[i];
if (target == strobe)
continue;
if (digitalRead(target) == LOW) {
for (int k = 0; k < 20; k++) {
if (keypad[k].strobe == strobe && keypad[k].target == target) {
// Visual and Audio feedback
Serial.print("Pressed: ");
Serial.println(keypad[k].key);
playBeep();
while (digitalRead(target) == LOW)
; // Wait for release
pinMode(strobe, INPUT_PULLUP);
return keypad[k].key;
}
}
}
}
pinMode(strobe, INPUT_PULLUP);
}
return '\0';
void setup() {
Serial.begin(115200);
startTime = millis();
}
void loop() {
getKeyPressed();
delay(10);
loopCount++;
if ((millis() - startTime) > 5000) {
Serial.print("Average loops per second = ");
Serial.println(loopCount / 5);
startTime = millis();
loopCount = 0;
}
if (kpd.getKeys()) {
for (int i = 0; i < LIST_MAX; i++) {
if (kpd.key[i].stateChanged) {
String msg = "";
switch (kpd.key[i].kstate) {
case PRESSED:
msg = " PRESSED.";
playBeep();
break;
case HOLD:
msg = " HOLD.";
break;
case RELEASED:
msg = " RELEASED.";
break;
case IDLE:
msg = " IDLE.";
break;
}
if (msg != "") {
Serial.print("Key ");
Serial.print(kpd.key[i].kchar);
Serial.println(msg);
}
}
}
}
}