Skip to content

Commit 6a8dafa

Browse files
committed
Version v0.05i "Stop the war in Ukraine"
- ST7789 TFT LCD SPI display support. - BMP280 sensor on I2C bus support. - AHT20 support. - TM1637 4-digit LED clock display support. - MCP4725 I2C 12-bit DAC support deprecated. - Program refactoring, better comments, various small bugs fixed.
1 parent 6602cfb commit 6a8dafa

File tree

2 files changed

+795
-194
lines changed

2 files changed

+795
-194
lines changed

extra/lcd_test_1a.ino

Lines changed: 312 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,312 @@
1+
// lcd_test_1a
2+
// by André Derrick Balsa (AndrewBCN)
3+
// March 2022
4+
// GPLV3
5+
// Testing the LCD display with the STM32F401CCU6
6+
// Also test SPI bus and I2C bus and various sensors
7+
8+
#if !defined(STM32_CORE_VERSION) || (STM32_CORE_VERSION < 0x02020000)
9+
#error "Due to API changes, this sketch is compatible with STM32_CORE_VERSION >= 0x02020000 (2.2.0 or later)"
10+
#endif
11+
12+
// Increase HardwareSerial (UART) TX and RX buffer sizes from default 64 characters to 256.
13+
// The main worry here is that we could miss some characters from the u-blox GPS module if
14+
// the processor is busy doing something else (e.g. updating the display, reading a sensor, etc)
15+
// specially since we increase the GPS baud rate from 9600 to 38400.
16+
17+
#define SERIAL_TX_BUFFER_SIZE 256 // Warning: > 256 could cause problems, see comments in STM32 HardwareSerial library
18+
#define SERIAL_RX_BUFFER_SIZE 256
19+
20+
#define GPSDO_GEN_2kHz_PB5 // generate 2kHz square wave test signal on pin PB5 using Timer 3
21+
#define GPSDO_INA219 // INA 219 current sensor
22+
23+
#ifdef GPSDO_GEN_2kHz_PB5
24+
#define Test2kHzOutputPin PB5 // digital output pin used to output a test 2kHz square wave
25+
#endif // GEN_2kHz_PB5
26+
27+
#ifdef GPSDO_INA219
28+
#include <Adafruit_INA219.h>
29+
Adafruit_INA219 ina219;
30+
#endif // INA219
31+
32+
#define VctlPWMOutputPin PB9 // digital output pin used to output a PWM value, TIM4 ch4
33+
// Two cascaded RC filters transform the PWM into an analog DC value
34+
35+
#include <Wire.h> // Hardware I2C library on STM32
36+
// Uses PB6 (SCL1) and PB7 (SDA1) on Black Pill for I2C1
37+
#include <SPI.h> // Hardware SPI library on STM32
38+
// Uses PA5, PA6, PA7 on Black Pill for SPI1
39+
// AHT20 - I2C
40+
#include <Adafruit_AHTX0.h> // Adafruit AHTX0 library for AHT20 I2C temperature and humidity sensor
41+
Adafruit_AHTX0 aht20; // create object aht20
42+
43+
// BMP280 - I2C
44+
#include <Adafruit_BMP280.h>
45+
Adafruit_BMP280 bmp280; // hardware I2C
46+
Adafruit_Sensor *bmp_temp = bmp280.getTemperatureSensor();
47+
Adafruit_Sensor *bmp_pressure = bmp280.getPressureSensor();
48+
49+
// TFT LCD ST7789 - SPI
50+
#include <Adafruit_GFX.h> // need this adapted for STM32F4xx/F411C: https://github.com/fpistm/Adafruit-GFX-Library/tree/Fix_pin_type
51+
#include <Adafruit_ST7789.h>
52+
//#include <Fonts/FreeSansBold18pt7b.h>
53+
54+
#define TFT_DC PB12 // note this pin assigment conflicts with the original GPSDO schematic
55+
#define TFT_CS PB13 // in reality, not connected, CS not used on 1.3" TFT ST7789 display
56+
#define TFT_RST PB15 // also uses pins PA5, PA6, PA7 for MOSI MISO and SCLK
57+
58+
Adafruit_ST7789 disp = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
59+
60+
// LEDs
61+
// Blue onboard LED blinks to indicate ISR is working
62+
#define blueledpin PC13 // Blue onboard LED is on PC13 on STM32F411CEU6 Black Pill
63+
// Yellow extra LED is off, on or blinking to indicate some GPSDO status
64+
#define yellowledpin PB8 // Yellow LED on PB8
65+
volatile int yellow_led_state = 2; // global variable 0=off 1=on 2=1Hz blink
66+
67+
// Uptime data
68+
volatile uint8_t uphours = 0;
69+
volatile uint8_t upminutes = 0;
70+
volatile uint8_t upseconds = 0;
71+
volatile uint16_t updays = 0;
72+
volatile bool halfsecond = false;
73+
char uptimestr[9] = "00:00:00"; // uptime string
74+
char updaysstr[5] = "000d"; // updays string
75+
76+
77+
// Interrupt Service Routine for the 2Hz timer
78+
void Timer_ISR_2Hz(void) { // WARNING! Do not attempt I2C communication inside the ISR
79+
80+
// Toggle pin. 2hz toogle --> 1Hz pulse, perfect 50% duty cycle
81+
digitalWrite(blueledpin, !digitalRead(blueledpin));
82+
83+
halfsecond = !halfsecond; // true @ 1Hz
84+
85+
switch (yellow_led_state)
86+
{
87+
case 0:
88+
// turn off led
89+
digitalWrite(yellowledpin, LOW);
90+
break;
91+
case 1:
92+
// turn on led
93+
digitalWrite(yellowledpin, HIGH);
94+
break;
95+
case 2:
96+
// blink led
97+
digitalWrite(yellowledpin, !digitalRead(yellowledpin));
98+
break;
99+
default:
100+
// default is to turn off led
101+
digitalWrite(yellowledpin, LOW);
102+
break;
103+
}
104+
105+
// Uptime clock - in days, hours, minutes, seconds
106+
if (halfsecond)
107+
{
108+
if (++upseconds > 59)
109+
{
110+
upseconds = 0;
111+
if (++upminutes > 59)
112+
{
113+
upminutes = 0;
114+
if (++uphours > 23)
115+
{
116+
uphours = 0;
117+
++updays;
118+
}
119+
}
120+
}
121+
}
122+
} // end of 2Hz ISR
123+
124+
void uptimetostrings() {
125+
// translate uptime variables to strings
126+
uptimestr[0] = '0' + uphours / 10;
127+
uptimestr[1] = '0' + uphours % 10;
128+
uptimestr[3] = '0' + upminutes / 10;
129+
uptimestr[4] = '0' + upminutes % 10;
130+
uptimestr[6] = '0' + upseconds / 10;
131+
uptimestr[7] = '0' + upseconds % 10;
132+
133+
if (updays > 99) { // 100 days or more
134+
updaysstr[0] = '0' + updays / 100;
135+
updaysstr[1] = '0' + (updays % 100) / 10;
136+
updaysstr[2] = '0' + (updays % 100) % 10;
137+
}
138+
else { // less than 100 days
139+
updaysstr[0] = '0';
140+
updaysstr[1] = '0' + updays / 10;
141+
updaysstr[2] = '0' + updays % 10;
142+
}
143+
}
144+
145+
void setup() {
146+
// Wait 1 second for things to stabilize
147+
delay(1000);
148+
149+
// setup USB serial
150+
Serial.begin(9600);
151+
Serial.println(F("LCD display test"));
152+
153+
// configure blueledpin in output mode
154+
pinMode(blueledpin, OUTPUT);
155+
156+
// configure yellow_led_pin in output mode
157+
pinMode(yellowledpin, OUTPUT);
158+
159+
// setup 2kHz test signal on PB5 if configured, uses Timer 3
160+
#ifdef GPSDO_GEN_2kHz_PB5 // note this uses Timer 3 Channel 2
161+
analogWrite(Test2kHzOutputPin, 127); // configures PB5 as PWM output pin at default frequency and resolution
162+
analogWriteFrequency(2000); // default PWM frequency is 1kHz, change it to 2kHz
163+
analogWriteResolution(16); // default PWM resolution is 8 bits, change it to 16 bits
164+
analogWrite(Test2kHzOutputPin, 32767); // 32767 for 16 bits -> 50% duty cycle so a square wave
165+
#endif // GEN_2kHz_PB5
166+
167+
// setup Vctl PWM DAC, output approximately 1.65V for testing purposes
168+
// we generate a 2kHz square wave on PB9 PWM pin, using Timer 4 channel 4
169+
// PB9 is Timer 4 Channel 4 from Arduino_Core_STM32/variants/STM32F4xx/F411C(C-E)(U-Y)/PeripheralPins_BLACKPILL_F411CE.c
170+
analogWrite(VctlPWMOutputPin, 127); // configures PB9 as PWM output pin at default frequency and resolution
171+
analogWriteFrequency(2000); // default PWM frequency is 1kHz, change it to 2kHz
172+
analogWriteResolution(16); // set PWM resolution to 16 bits (the maximum for the STM32F411CEU6)
173+
analogWrite(VctlPWMOutputPin, 32767); // 32767 for 16 bits -> 50% duty cycle so a square wave
174+
175+
// setup 2Hz timer and interrupt, uses Timer 9
176+
HardwareTimer *tim2Hz = new HardwareTimer(TIM9);
177+
tim2Hz->setOverflow(2, HERTZ_FORMAT); // 2 Hz
178+
tim2Hz->attachInterrupt(Timer_ISR_2Hz);
179+
tim2Hz->resume();
180+
181+
// setup sensors and LCD display
182+
// AHT20, BMP280, INA219, ST7789 240x240 TFT LCD
183+
184+
Serial.println(F("Testing for presence of AHT20 Sensor on I2C bus"));
185+
if (!aht20.begin()) {
186+
Serial.println(F("Could not find AHT20 sensor, check wiring"));
187+
while (1) delay(10);
188+
}
189+
else Serial.println(F("AHT20 sensor found!"));
190+
191+
Serial.println(F("Testing for presence of BMP280 Sensor on I2C bus"));
192+
if (!bmp280.begin(0x76,0x58)) {
193+
Serial.println(F("Could not find BMP280 sensor, check wiring"));
194+
while (1) delay(10);
195+
}
196+
else Serial.println(F("BMP280 sensor found!"));
197+
198+
// Default settings from datasheet
199+
bmp280.setSampling(Adafruit_BMP280::MODE_NORMAL, // Operating Mode
200+
Adafruit_BMP280::SAMPLING_X2, // Temp. oversampling
201+
Adafruit_BMP280::SAMPLING_X16, // Pressure oversampling
202+
Adafruit_BMP280::FILTER_X16, // Filtering
203+
Adafruit_BMP280::STANDBY_MS_500); // Standby time
204+
205+
// Initialize the INA219.
206+
// By default the initialization will use the largest range (32V, 2A). However
207+
// you can call a setCalibration function to change this range (see comments).
208+
if (! ina219.begin()) {
209+
Serial.println(F("Could not find INA219 sensor, check wiring"));
210+
while (1) { delay(10); }
211+
}
212+
else Serial.println(F("INA219 sensor found!"));
213+
// To use a slightly lower 32V, 1A range (higher precision on amps):
214+
//ina219.setCalibration_32V_1A();
215+
// Or to use a lower 16V, 400mA range (higher precision on volts and amps):
216+
//ina219.setCalibration_16V_400mA();
217+
ina219.setCalibration_32V_1A();
218+
219+
// Setup 240x240 LCD SPI ST7789 display
220+
disp.init(240, 240, SPI_MODE3); // 1.3" 240x240 TFT LCD
221+
delay(500);
222+
disp.fillScreen(ST77XX_BLACK);
223+
disp.setTextColor(ST77XX_YELLOW, ST77XX_BLACK); //
224+
disp.setRotation(2); // 0..3 max, here we use 180° = landscape
225+
disp.setFont();
226+
disp.setTextSize(3);
227+
disp.setCursor(0, 30);
228+
disp.print(F("Testing..."));
229+
disp.setTextSize(2);
230+
disp.setCursor(0, 60);
231+
disp.setTextColor(ST77XX_GREEN, ST77XX_BLACK);
232+
disp.print(F(" Smaller text - "));
233+
disp.setTextColor(ST77XX_WHITE, ST77XX_BLACK);
234+
disp.print(F("123"));
235+
disp.setCursor(0, 80);
236+
disp.setTextColor(ST77XX_RED, ST77XX_BLACK);
237+
disp.print(F("Different colors."));
238+
disp.setTextSize(3);
239+
disp.setTextColor(ST77XX_CYAN, ST77XX_BLACK);
240+
disp.setCursor(0, 120);
241+
disp.print(F("STM32 GPSDO"));
242+
disp.setTextSize(2);
243+
disp.setTextColor(ST77XX_MAGENTA, ST77XX_BLACK);
244+
disp.setCursor(0, 150);
245+
disp.print(F(" Version v0.99z"));
246+
disp.setTextColor(ST77XX_BLUE, ST77XX_BLACK);
247+
disp.setCursor(0, 180);
248+
disp.print(F(" ... not really!"));
249+
} // setup done
250+
251+
void loop() {
252+
// print something once per second to USB serial (Arduino monitor)
253+
254+
uptimetostrings(); // get updaysstr and uptimestr
255+
Serial.print(F("Uptime: "));
256+
Serial.print(updaysstr);
257+
Serial.print(F(" "));
258+
Serial.println(uptimestr);
259+
260+
Serial.println();
261+
262+
sensors_event_t temp_event, pressure_event;
263+
bmp_temp->getEvent(&temp_event);
264+
bmp_pressure->getEvent(&pressure_event);
265+
266+
Serial.println(F("BMP280 Sensor Readings"));
267+
Serial.print(F("Temperature = "));
268+
Serial.print(temp_event.temperature);
269+
Serial.println(F(" *C"));
270+
271+
Serial.print(F("Pressure = "));
272+
Serial.print(pressure_event.pressure);
273+
Serial.println(F(" hPa"));
274+
275+
Serial.println();
276+
277+
Serial.println(F("AHT20 Sensor Readings"));
278+
sensors_event_t humidity, temp;
279+
aht20.getEvent(&humidity, &temp); // populate temp and humidity objects with fresh data
280+
Serial.print(F("Temperature = "));
281+
Serial.print(temp.temperature);
282+
Serial.println(F(" *C"));
283+
284+
Serial.print(F("Humidity = "));
285+
Serial.print(humidity.relative_humidity);
286+
Serial.println(F("% rH"));
287+
288+
Serial.println();
289+
290+
// Read INA 219 current voltage sensor
291+
float shuntvoltage = 0;
292+
float busvoltage = 0;
293+
float current_mA = 0;
294+
float loadvoltage = 0;
295+
float power_mW = 0;
296+
297+
shuntvoltage = ina219.getShuntVoltage_mV();
298+
busvoltage = ina219.getBusVoltage_V();
299+
current_mA = ina219.getCurrent_mA();
300+
power_mW = ina219.getPower_mW();
301+
loadvoltage = busvoltage + (shuntvoltage / 1000);
302+
303+
Serial.print("Bus Voltage: "); Serial.print(busvoltage); Serial.println(" V");
304+
Serial.print("Shunt Voltage: "); Serial.print(shuntvoltage); Serial.println(" mV");
305+
Serial.print("Load Voltage: "); Serial.print(loadvoltage); Serial.println(" V");
306+
Serial.print("Current: "); Serial.print(current_mA); Serial.println(" mA");
307+
Serial.print("Power: "); Serial.print(power_mW); Serial.println(" mW");
308+
309+
Serial.println("");
310+
311+
delay(2000);
312+
}

0 commit comments

Comments
 (0)