diff --git a/extra/lcd_test_1a.ino b/extra/lcd_test_1a.ino new file mode 100644 index 0000000..ac40652 --- /dev/null +++ b/extra/lcd_test_1a.ino @@ -0,0 +1,312 @@ +// lcd_test_1a +// by André Derrick Balsa (AndrewBCN) +// March 2022 +// GPLV3 +// Testing the LCD display with the STM32F401CCU6 +// Also test SPI bus and I2C bus and various sensors + +#if !defined(STM32_CORE_VERSION) || (STM32_CORE_VERSION < 0x02020000) + #error "Due to API changes, this sketch is compatible with STM32_CORE_VERSION >= 0x02020000 (2.2.0 or later)" +#endif + +// Increase HardwareSerial (UART) TX and RX buffer sizes from default 64 characters to 256. +// The main worry here is that we could miss some characters from the u-blox GPS module if +// the processor is busy doing something else (e.g. updating the display, reading a sensor, etc) +// specially since we increase the GPS baud rate from 9600 to 38400. + +#define SERIAL_TX_BUFFER_SIZE 256 // Warning: > 256 could cause problems, see comments in STM32 HardwareSerial library +#define SERIAL_RX_BUFFER_SIZE 256 + +#define GPSDO_GEN_2kHz_PB5 // generate 2kHz square wave test signal on pin PB5 using Timer 3 +#define GPSDO_INA219 // INA 219 current sensor + +#ifdef GPSDO_GEN_2kHz_PB5 + #define Test2kHzOutputPin PB5 // digital output pin used to output a test 2kHz square wave +#endif // GEN_2kHz_PB5 + +#ifdef GPSDO_INA219 + #include + Adafruit_INA219 ina219; +#endif // INA219 + +#define VctlPWMOutputPin PB9 // digital output pin used to output a PWM value, TIM4 ch4 + // Two cascaded RC filters transform the PWM into an analog DC value + +#include // Hardware I2C library on STM32 + // Uses PB6 (SCL1) and PB7 (SDA1) on Black Pill for I2C1 +#include // Hardware SPI library on STM32 + // Uses PA5, PA6, PA7 on Black Pill for SPI1 +// AHT20 - I2C +#include // Adafruit AHTX0 library for AHT20 I2C temperature and humidity sensor +Adafruit_AHTX0 aht20; // create object aht20 + +// BMP280 - I2C +#include +Adafruit_BMP280 bmp280; // hardware I2C +Adafruit_Sensor *bmp_temp = bmp280.getTemperatureSensor(); +Adafruit_Sensor *bmp_pressure = bmp280.getPressureSensor(); + +// TFT LCD ST7789 - SPI +#include // need this adapted for STM32F4xx/F411C: https://github.com/fpistm/Adafruit-GFX-Library/tree/Fix_pin_type +#include +//#include + +#define TFT_DC PB12 // note this pin assigment conflicts with the original GPSDO schematic +#define TFT_CS PB13 // in reality, not connected, CS not used on 1.3" TFT ST7789 display +#define TFT_RST PB15 // also uses pins PA5, PA6, PA7 for MOSI MISO and SCLK + +Adafruit_ST7789 disp = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST); + +// LEDs +// Blue onboard LED blinks to indicate ISR is working +#define blueledpin PC13 // Blue onboard LED is on PC13 on STM32F411CEU6 Black Pill +// Yellow extra LED is off, on or blinking to indicate some GPSDO status +#define yellowledpin PB8 // Yellow LED on PB8 +volatile int yellow_led_state = 2; // global variable 0=off 1=on 2=1Hz blink + +// Uptime data +volatile uint8_t uphours = 0; +volatile uint8_t upminutes = 0; +volatile uint8_t upseconds = 0; +volatile uint16_t updays = 0; +volatile bool halfsecond = false; +char uptimestr[9] = "00:00:00"; // uptime string +char updaysstr[5] = "000d"; // updays string + + +// Interrupt Service Routine for the 2Hz timer +void Timer_ISR_2Hz(void) { // WARNING! Do not attempt I2C communication inside the ISR + + // Toggle pin. 2hz toogle --> 1Hz pulse, perfect 50% duty cycle + digitalWrite(blueledpin, !digitalRead(blueledpin)); + + halfsecond = !halfsecond; // true @ 1Hz + + switch (yellow_led_state) + { + case 0: + // turn off led + digitalWrite(yellowledpin, LOW); + break; + case 1: + // turn on led + digitalWrite(yellowledpin, HIGH); + break; + case 2: + // blink led + digitalWrite(yellowledpin, !digitalRead(yellowledpin)); + break; + default: + // default is to turn off led + digitalWrite(yellowledpin, LOW); + break; + } + + // Uptime clock - in days, hours, minutes, seconds + if (halfsecond) + { + if (++upseconds > 59) + { + upseconds = 0; + if (++upminutes > 59) + { + upminutes = 0; + if (++uphours > 23) + { + uphours = 0; + ++updays; + } + } + } + } +} // end of 2Hz ISR + +void uptimetostrings() { + // translate uptime variables to strings + uptimestr[0] = '0' + uphours / 10; + uptimestr[1] = '0' + uphours % 10; + uptimestr[3] = '0' + upminutes / 10; + uptimestr[4] = '0' + upminutes % 10; + uptimestr[6] = '0' + upseconds / 10; + uptimestr[7] = '0' + upseconds % 10; + + if (updays > 99) { // 100 days or more + updaysstr[0] = '0' + updays / 100; + updaysstr[1] = '0' + (updays % 100) / 10; + updaysstr[2] = '0' + (updays % 100) % 10; + } + else { // less than 100 days + updaysstr[0] = '0'; + updaysstr[1] = '0' + updays / 10; + updaysstr[2] = '0' + updays % 10; + } +} + +void setup() { + // Wait 1 second for things to stabilize + delay(1000); + + // setup USB serial + Serial.begin(9600); + Serial.println(F("LCD display test")); + + // configure blueledpin in output mode + pinMode(blueledpin, OUTPUT); + + // configure yellow_led_pin in output mode + pinMode(yellowledpin, OUTPUT); + + // setup 2kHz test signal on PB5 if configured, uses Timer 3 + #ifdef GPSDO_GEN_2kHz_PB5 // note this uses Timer 3 Channel 2 + analogWrite(Test2kHzOutputPin, 127); // configures PB5 as PWM output pin at default frequency and resolution + analogWriteFrequency(2000); // default PWM frequency is 1kHz, change it to 2kHz + analogWriteResolution(16); // default PWM resolution is 8 bits, change it to 16 bits + analogWrite(Test2kHzOutputPin, 32767); // 32767 for 16 bits -> 50% duty cycle so a square wave + #endif // GEN_2kHz_PB5 + + // setup Vctl PWM DAC, output approximately 1.65V for testing purposes + // we generate a 2kHz square wave on PB9 PWM pin, using Timer 4 channel 4 + // PB9 is Timer 4 Channel 4 from Arduino_Core_STM32/variants/STM32F4xx/F411C(C-E)(U-Y)/PeripheralPins_BLACKPILL_F411CE.c + analogWrite(VctlPWMOutputPin, 127); // configures PB9 as PWM output pin at default frequency and resolution + analogWriteFrequency(2000); // default PWM frequency is 1kHz, change it to 2kHz + analogWriteResolution(16); // set PWM resolution to 16 bits (the maximum for the STM32F411CEU6) + analogWrite(VctlPWMOutputPin, 32767); // 32767 for 16 bits -> 50% duty cycle so a square wave + + // setup 2Hz timer and interrupt, uses Timer 9 + HardwareTimer *tim2Hz = new HardwareTimer(TIM9); + tim2Hz->setOverflow(2, HERTZ_FORMAT); // 2 Hz + tim2Hz->attachInterrupt(Timer_ISR_2Hz); + tim2Hz->resume(); + + // setup sensors and LCD display + // AHT20, BMP280, INA219, ST7789 240x240 TFT LCD + + Serial.println(F("Testing for presence of AHT20 Sensor on I2C bus")); + if (!aht20.begin()) { + Serial.println(F("Could not find AHT20 sensor, check wiring")); + while (1) delay(10); + } + else Serial.println(F("AHT20 sensor found!")); + + Serial.println(F("Testing for presence of BMP280 Sensor on I2C bus")); + if (!bmp280.begin(0x76,0x58)) { + Serial.println(F("Could not find BMP280 sensor, check wiring")); + while (1) delay(10); + } + else Serial.println(F("BMP280 sensor found!")); + + // Default settings from datasheet + bmp280.setSampling(Adafruit_BMP280::MODE_NORMAL, // Operating Mode + Adafruit_BMP280::SAMPLING_X2, // Temp. oversampling + Adafruit_BMP280::SAMPLING_X16, // Pressure oversampling + Adafruit_BMP280::FILTER_X16, // Filtering + Adafruit_BMP280::STANDBY_MS_500); // Standby time + + // Initialize the INA219. + // By default the initialization will use the largest range (32V, 2A). However + // you can call a setCalibration function to change this range (see comments). + if (! ina219.begin()) { + Serial.println(F("Could not find INA219 sensor, check wiring")); + while (1) { delay(10); } + } + else Serial.println(F("INA219 sensor found!")); + // To use a slightly lower 32V, 1A range (higher precision on amps): + //ina219.setCalibration_32V_1A(); + // Or to use a lower 16V, 400mA range (higher precision on volts and amps): + //ina219.setCalibration_16V_400mA(); + ina219.setCalibration_32V_1A(); + + // Setup 240x240 LCD SPI ST7789 display + disp.init(240, 240, SPI_MODE3); // 1.3" 240x240 TFT LCD + delay(500); + disp.fillScreen(ST77XX_BLACK); + disp.setTextColor(ST77XX_YELLOW, ST77XX_BLACK); // + disp.setRotation(2); // 0..3 max, here we use 180° = landscape + disp.setFont(); + disp.setTextSize(3); + disp.setCursor(0, 30); + disp.print(F("Testing...")); + disp.setTextSize(2); + disp.setCursor(0, 60); + disp.setTextColor(ST77XX_GREEN, ST77XX_BLACK); + disp.print(F(" Smaller text - ")); + disp.setTextColor(ST77XX_WHITE, ST77XX_BLACK); + disp.print(F("123")); + disp.setCursor(0, 80); + disp.setTextColor(ST77XX_RED, ST77XX_BLACK); + disp.print(F("Different colors.")); + disp.setTextSize(3); + disp.setTextColor(ST77XX_CYAN, ST77XX_BLACK); + disp.setCursor(0, 120); + disp.print(F("STM32 GPSDO")); + disp.setTextSize(2); + disp.setTextColor(ST77XX_MAGENTA, ST77XX_BLACK); + disp.setCursor(0, 150); + disp.print(F(" Version v0.99z")); + disp.setTextColor(ST77XX_BLUE, ST77XX_BLACK); + disp.setCursor(0, 180); + disp.print(F(" ... not really!")); +} // setup done + +void loop() { + // print something once per second to USB serial (Arduino monitor) + + uptimetostrings(); // get updaysstr and uptimestr + Serial.print(F("Uptime: ")); + Serial.print(updaysstr); + Serial.print(F(" ")); + Serial.println(uptimestr); + + Serial.println(); + + sensors_event_t temp_event, pressure_event; + bmp_temp->getEvent(&temp_event); + bmp_pressure->getEvent(&pressure_event); + + Serial.println(F("BMP280 Sensor Readings")); + Serial.print(F("Temperature = ")); + Serial.print(temp_event.temperature); + Serial.println(F(" *C")); + + Serial.print(F("Pressure = ")); + Serial.print(pressure_event.pressure); + Serial.println(F(" hPa")); + + Serial.println(); + + Serial.println(F("AHT20 Sensor Readings")); + sensors_event_t humidity, temp; + aht20.getEvent(&humidity, &temp); // populate temp and humidity objects with fresh data + Serial.print(F("Temperature = ")); + Serial.print(temp.temperature); + Serial.println(F(" *C")); + + Serial.print(F("Humidity = ")); + Serial.print(humidity.relative_humidity); + Serial.println(F("% rH")); + + Serial.println(); + + // Read INA 219 current voltage sensor + float shuntvoltage = 0; + float busvoltage = 0; + float current_mA = 0; + float loadvoltage = 0; + float power_mW = 0; + + shuntvoltage = ina219.getShuntVoltage_mV(); + busvoltage = ina219.getBusVoltage_V(); + current_mA = ina219.getCurrent_mA(); + power_mW = ina219.getPower_mW(); + loadvoltage = busvoltage + (shuntvoltage / 1000); + + Serial.print("Bus Voltage: "); Serial.print(busvoltage); Serial.println(" V"); + Serial.print("Shunt Voltage: "); Serial.print(shuntvoltage); Serial.println(" mV"); + Serial.print("Load Voltage: "); Serial.print(loadvoltage); Serial.println(" V"); + Serial.print("Current: "); Serial.print(current_mA); Serial.println(" mA"); + Serial.print("Power: "); Serial.print(power_mW); Serial.println(" mW"); + + Serial.println(""); + + delay(2000); +} diff --git a/software/GPSDO.ino b/software/GPSDO.ino index df77d7c..9aa8235 100644 --- a/software/GPSDO.ino +++ b/software/GPSDO.ino @@ -1,5 +1,5 @@ /********************************************************************************************************** - STM32 GPSDO v0.05f by André Balsa, February 2022 + STM32 GPSDO v0.05i by André Balsa, March 2022 GPLV3 license Reuses small bits of the excellent GPS checker code Arduino sketch by Stuart Robinson - 05/04/20 From version 0.03 includes a command parser, so the GPSDO can receive commands from the USB serial or @@ -74,10 +74,10 @@ - U8g2/u8x8 graphics library, see https://github.com/olikraus/u8g2 - Adafruit AHTX0 - Adafruit BMP280 - - Adafruit MCP4725 12-bit DAC library (not needed if using the recommended 16-bit PWM DAC) - movingAvg library, on STM32 architecture needs a simple patch to avoid warning during compilation - Color LCD support requires the installation of the Adafruit ST7735 and ST7789 LCD library and the Adafruit GFX library. + - TM1637 LED clock module requires the TM1637 library, see https://github.com/avishorp/TM1637 For commands parsing, uses SerialCommands library found here: https://github.com/ppedro74/Arduino-SerialCommands @@ -106,7 +106,7 @@ Arduino IDE serial monitor and updates the seconds without a fix on the display. During this time the NMEA stream coming from the GPS is copied to the serial monitor also. The DFLL is active as soon as the GPS starts providing a 1PPS pulse. The 10MHz OCXO is controlled by a voltage generated by either - the 16-bit PWM or the MCP4725 I2C DAC; this voltage (Vctl) is adjusted once every 429 seconds. + the 16-bit PWM ; this voltage (Vctl) is adjusted once every 429 seconds. **********************************************************************************************************/ // Version 0.04i and later: Erik Kaashoek has suggested a 10s sampling rate for the 64-bit counter, to save RAM. @@ -115,18 +115,16 @@ // Version 0.05d and later have the code for setup() and loop() moved to the very bottom of this file, and // include support for an SPI LCD display, with code contributed by Badwater-Frank. -// Enabling the INA219 sensor using the LapINA219 library causes the firmware to lock up after a few minutes -// I have not identified the cause, it could be the library, or a hardware issue, or I have a bad sensor, etc. -// Requires further testing with another INA219 sensor, or another library. -// Note that leaving the INA219 sensor on the I2C bus without otherwise reading from / writing to it, does -// not cause any lock up. +// Version 0.05i and later will progressively deprecate the use of the MCP4725 I2C 12-bit DAC. -// TODO when I have the time: -// 1. Solve the INA219 puzzle. -// 2. Refactor the setup and main loop functions to make them as simple as possible. +// 1. picDIV synchronization control. +// 2. Refactor the entire program to make it easier to understand and maintain. +// 3. Implement support for the STM32F401CCU6 Black Pill. +// 4. Frequency / period meter implementation. +// 5. Improve layout of ST7789 display. #define Program_Name "GPSDO" -#define Program_Version "v0.05f" +#define Program_Version "v0.05i" #define Author_Name "André Balsa" // Debug options @@ -137,15 +135,16 @@ // Hardware options // ---------------- // #define GPSDO_STM32F401 // use an STM32F401 Black Pill instead of STM32F411 (reduced RAM) + // IMPORTANT! Don't forget to select the correct board in the Tools->Board menu in the arduino IDE #define GPSDO_OLED // SSD1306 128x64 I2C OLED display // #define GPSDO_LCD_ST7735 // ST7735 160x128 SPI LCD display -// #define GPSDO_LCD_ST7789 // ST7789 240x240 SPI LCD display -// #define GPSDO_MCP4725 // MCP4725 I2C 12-bit DAC -#define GPSDO_PWM_DAC // STM32 16-bit PWM DAC, requires two rc filters (2xr=20k, 2xc=10uF) -#define GPSDO_AHT10 // I2C temperature and humidity sensor +#define GPSDO_LCD_ST7789 // ST7789 240x240 SPI LCD display (testing) +#define GPSDO_PWM_DAC // STM32 16-bit PWM DAC, requires two rc filters (2xr=20k, 2xc=10uF) - note this will become the default +#define GPSDO_AHT10 // AHT10 or AHT20 (recommended) I2C temperature and humidity sensor #define GPSDO_GEN_2kHz_PB5 // generate 2kHz square wave test signal on pin PB5 using Timer 3 -#define GPSDO_BMP280_SPI // SPI atmospheric pressure, temperature and altitude sensor -// #define GPSDO_INA219 // INA219 I2C current and voltage sensor +// #define GPSDO_BMP280_SPI // SPI atmospheric pressure, temperature and altitude sensor +#define GPSDO_BMP280_I2C // I2C atmospheric pressure, temperature and altitude sensor +#define GPSDO_INA219 // INA219 I2C current and voltage sensor // #define GPSDO_BLUETOOTH // Bluetooth serial (HC-06 module) #define GPSDO_VCC // Vcc (nominal 5V) ; reading Vcc requires 1:2 voltage divider to PA0 #define GPSDO_VDD // Vdd (nominal 3.3V) reads VREF internal ADC channel @@ -153,11 +152,12 @@ #define GPSDO_UBX_CONFIG // optimize u-blox GPS receiver configuration #define GPSDO_VERBOSE_NMEA // GPS module NMEA stream echoed to USB serial xor Bluetooth serial // #define GPSDO_PICDIV // generate a 1.2s synchronization pulse for the picDIV +#define GPSDO_TM1637 // TM1637 4-digit LED module // Includes // -------- #if !defined(STM32_CORE_VERSION) || (STM32_CORE_VERSION < 0x02020000) -#error "Due to API changes, this sketch is compatible with STM32_CORE_VERSION >= 0x02020000 (2.2.0 or later)" + #error "Due to API changes, this sketch is compatible with STM32_CORE_VERSION >= 0x02020000 (2.2.0 or later)" #endif // Increase HardwareSerial (UART) TX and RX buffer sizes from default 64 characters to 256. @@ -175,139 +175,147 @@ const uint16_t waitFixTime = 1; // Maximum time in seconds waiting for a // to avoid warning message during compilation #ifdef GPSDO_PICDIV -#define picDIVsyncPin PB3 // digital output pin used to generate a 1.2s synchronization pulse for the picDIV + #define picDIVsyncPin PB3 // digital output pin used to generate a 1.2s synchronization pulse for the picDIV #endif // PICDIV #ifdef GPSDO_GEN_2kHz_PB5 -#define Test2kHzOutputPin PB5 // digital output pin used to output a test 2kHz square wave + #define Test2kHzOutputPin PB5 // digital output pin used to output a test 2kHz square wave #endif // GEN_2kHz_PB5 +// HC-06 Bluetooth module #ifdef GPSDO_BLUETOOTH -// UART RX TX -HardwareSerial Serial2(PA3, PA2); // Serial connection to HC-06 Bluetooth module + // UART RX TX + HardwareSerial Serial2(PA3, PA2); // Serial connection to HC-06 Bluetooth module + #define BT_BAUD 57600 // Bluetooth baud rate #endif // BLUETOOTH -#define BT_BAUD 57600 // Bluetooth baud rate #include // Commands parser library char serial_command_buffer_[32]; // buffer for commands library // The following line determines which serial port we'll listen to // "\n" means only newline needed to accept command #ifdef GPSDO_BLUETOOTH -SerialCommands serial_commands_(&Serial2, serial_command_buffer_, sizeof(serial_command_buffer_), "\n", " "); + SerialCommands serial_commands_(&Serial2, serial_command_buffer_, sizeof(serial_command_buffer_), "\n", " "); #else -SerialCommands serial_commands_(&Serial, serial_command_buffer_, sizeof(serial_command_buffer_), "\n", " "); + SerialCommands serial_commands_(&Serial, serial_command_buffer_, sizeof(serial_command_buffer_), "\n", " "); #endif // BLUETOOTH #include // get library here > http://arduiniana.org/libraries/tinygpsplus/ TinyGPSPlus gps; // create the TinyGPS++ object #include // Hardware I2C library on STM32 - // Uses PB6 (SCL1) and PB7 (SDA1) on Black Pill for I2C1 + +// AHT10 / AHT20 temperature humidity sensor // Uses PB6 (SCL1) and PB7 (SDA1) on Black Pill for I2C1 #ifdef GPSDO_AHT10 -#include // Adafruit AHTX0 library -Adafruit_AHTX0 aht; // create object aht + #include // Adafruit AHTX0 library + Adafruit_AHTX0 aht; // create object aht #endif // AHT10 +// INA219 current voltage sensor #ifdef GPSDO_INA219 -#include // LapINA219 library library -LapINA219 ina219(0x40); // create object ina219 with I2C address 0x40 -float ina219volt=0.0, ina219curr=0.0; -TwoWire Wire3(PB4,PA8); // Second TwoWire instance for INA219 on SDA3/SCL3 (should be put somewhere more fitting but must stay global) + #include + Adafruit_INA219 ina219; + float ina219volt=0.0, ina219curr=0.0; #endif // INA219 +// TM1637 4-digit LED module +#ifdef GPSDO_TM1637 + #include // get library here > https://github.com/avishorp/TM1637 + // Module connection pins (Digital Pins) + #define CLK PA8 // interface to TM1637 requires two GPIO pins + #define DIO PB4 + TM1637Display tm1637(CLK, DIO); // create tm1637 object +#endif // TM1637 + // OLED 0.96 SSD1306 128x64 #ifdef GPSDO_OLED -#include // get library here > https://github.com/olikraus/u8g2 -U8X8_SSD1306_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); // use this line for standard 0.96" SSD1306 + #include // get library here > https://github.com/olikraus/u8g2 + U8X8_SSD1306_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); // use this line for standard 0.96" SSD1306 #endif // OLED // LCD 1.8" ST7735 160x128 (tested by Badwater-Frank) #ifdef GPSDO_LCD_ST7735 -#include // need this adapted for STM32F4xx/F411C: https://github.com/fpistm/Adafruit-GFX-Library/tree/Fix_pin_type -#include -//#include -#include -#define TFT_DC PA1 // note this pin assigment conflicts with the original schematic -#define TFT_CS PA2 -#define TFT_RST PA3 -// For 1.44" and 1.8" TFT with ST7735 use: -Adafruit_ST7735 disp = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); -#endif // LCD - -// LCD 1.8" ST7789 240x240 WARNING!!! NOT TESTED YET -#ifdef GPSDO_LCD -#include // need this adapted for STM32F4xx/F411C: https://github.com/fpistm/Adafruit-GFX-Library/tree/Fix_pin_type -#include -//#include -#include -#define TFT_DC PA1 // note this pin assigment conflicts with the original schematic -#define TFT_CS PA2 -#define TFT_RST PA3 -// For 1.8" TFT with ST7789 use: -Adafruit_ST7789 disp = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST); -#endif // LCD - -#ifdef GPSDO_MCP4725 -#include // MCP4725 12-bit DAC Adafruit library -Adafruit_MCP4725 dac; -const uint16_t default_DAC_output = 2400; // 12-bit value, varies from OCXO to OCXO, and with aging and temperature - // Some values I have been using, determined empirically: - // 2603 for an ISOTEMP 143-141 - // 2549 for a CTI OSC5A2B02 - // 2400 for an NDK ENE3311B - // 2180 for a second NDK ENE3311B -uint16_t adjusted_DAC_output; // we adjust this value to "close the loop" of the DFLL when using the DAC -#endif // MCP4725 + #include // need this adapted for STM32F4xx/F411C: https://github.com/fpistm/Adafruit-GFX-Library/tree/Fix_pin_type + #include + //#include + #include + #define TFT_DC PA1 // note this pin assigment conflicts with the original schematic + #define TFT_CS PA2 + #define TFT_RST PA3 + // For 1.44" and 1.8" TFT with ST7735 use: + Adafruit_ST7735 disp = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); +#endif // LCD_ST7735 +// LCD 1.3" ST7789 240x240 (Testing) +#ifdef GPSDO_LCD_ST7789 + #include // need this adapted for STM32F4xx/F411C: https://github.com/fpistm/Adafruit-GFX-Library/tree/Fix_pin_type + #include + //#include + #include + #define TFT_DC PB12 // note pin assigment that does not conflict with other interfaces + #define TFT_CS PB13 // in reality, CS not connected, CS not used on 1.3" TFT ST7789 display + #define TFT_RST PB15 // also uses pins PA5, PA6, PA7 for MOSI MISO and SCLK + // For 1.3" LCD with ST7789 + Adafruit_ST7789 disp_st7789 = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST); +#endif // LCD_ST7789 + +// PWM 16-bit DAC const uint16_t default_PWM_output = 35585; // "ideal" 16-bit PWM value, varies with OCXO, RC network, and time and temperature // 35585 for a second NDK ENE3311B uint16_t adjusted_PWM_output; // we adjust this value to "close the loop" of the DFLL when using the PWM volatile bool must_adjust_DAC = false; // true when there is enough data to adjust Vctl char trendstr[5] = " ___"; // PWM trend string, set in the adjustVctlPWM() function -#define VctlInputPin PB0 // ADC pin to read Vctl from DAC - #define VctlPWMOutputPin PB9 // digital output pin used to output a PWM value, TIM4 ch4 // Two cascaded RC filters transform the PWM into an analog DC value #define VctlPWMInputPin PB1 // ADC pin to read Vctl from filtered PWM +volatile int pwmVctl = 0; // variable used to store PWM Vctl read by ADC pin PB1 -volatile int dacVctl = 0; // DAC Vctl read by ADC pin PB0 -volatile int pwmVctl = 0; // PWM Vctl read by ADC pin PB1 - +// VCC - 5V #ifdef GPSDO_VCC -#define VccDiv2InputPin PA0 // Vcc/2 using resistor divider connects to PA0 -int adcVcc = 0; + #define VccDiv2InputPin PA0 // Vcc/2 using resistor divider connects to PA0 + int adcVcc = 0; #endif // VCC +// VDD - 3.3V #ifdef GPSDO_VDD -int adcVdd = 0; // Vdd is read internally as Vref + int adcVdd = 0; // Vdd is read internally as Vref #endif // VDD // movingAvg objects for the voltages measured by MCU ADC // all averages over 10 samples (10 seconds in principle) #ifdef GPSDO_VDD -movingAvg avg_adcVdd(10); -int16_t avgVdd = 0; + movingAvg avg_adcVdd(10); + int16_t avgVdd = 0; #endif // VDD + #ifdef GPSDO_VCC -movingAvg avg_adcVcc(10); -int16_t avgVcc = 0; + movingAvg avg_adcVcc(10); + int16_t avgVcc = 0; #endif // VCC -movingAvg avg_dacVctl(10); -int16_t avgdacVctl = 0; + movingAvg avg_pwmVctl(10); int16_t avgpwmVctl = 0; +// BMP280 atmospheric pressure and temperature sensor #ifdef GPSDO_BMP280_SPI -// BMP280 - SPI -#include -#include -#define BMP280_CS (PA4) // SPI1 uses PA4, PA5, PA6, PA7 -Adafruit_BMP280 bmp(BMP280_CS); // hardware SPI, use PA4 as Chip Select -const uint16_t PressureOffset = 1860; // that offset must be calculated for your sensor and location -float bmp280temp=0.0, bmp280pres=0.0, bmp280alti=0.0; // read sensor, save here + // BMP280 - SPI + #include + #include + #define BMP280_CS (PA4) // SPI1 uses PA4, PA5, PA6, PA7 + Adafruit_BMP280 bmp(BMP280_CS); // hardware SPI, use PA4 as Chip Select #endif // BMP280_SPI +#ifdef GPSDO_BMP280_I2C + // BMP280 - I2C + #include + Adafruit_BMP280 bmp; // hardware I2C +#endif // BMP280_I2C + +#if (defined (GPSDO_BMP280_SPI) || defined (GPSDO_BMP280_I2C)) + const uint16_t PressureOffset = 1860; // that offset must be calculated for your sensor and location + float bmp280temp=0.0, bmp280pres=0.0, bmp280alti=0.0; // read sensor, save here +#endif // BMP280 + // LEDs // Blue onboard LED blinks to indicate ISR is working #define blueledpin PC13 // Blue onboard LED is on PC13 on STM32F411CEU6 Black Pill @@ -384,8 +392,10 @@ volatile bool flush_ring_buffers_flag = true; // indicates ring buffers should // Miscellaneous data structures +// picDIV support #ifdef GPSDO_PICDIV -volatile bool force_armpicDIV_flag = true; // indicates picDIV must be armed waiting to sync on next PPS from GPS module + #define VphaseInputPin PB1 // ADC pin to read Vphase from 1ns-resolution TIC + volatile bool force_armpicDIV_flag = true; // indicates picDIV must be armed waiting to sync on next PPS from GPS module #endif // PICDIV volatile bool force_calibration_flag = true; // indicates GPSDO should start calibration sequence @@ -402,9 +412,9 @@ volatile bool ocxo_needs_warming = true; // indicates OCXO needs to warm u volatile bool tunnel_mode_flag = false; // the GPSDO relays the information directly to and from the GPS module to the USB serial #ifdef TunnelModeTesting -const uint16_t tunnelSecs = 15; // tunnel mode timeout in seconds; 15s for testing, 300s or 600s normal use + const uint16_t tunnelSecs = 15; // tunnel mode timeout in seconds; 15s for testing, 300s or 600s normal use #else -const uint16_t tunnelSecs = 300; // tunnel mode timeout in seconds; 15s for testing, 300s or 600s normal use + const uint16_t tunnelSecs = 300; // tunnel mode timeout in seconds; 15s for testing, 300s or 600s normal use #endif // TunnelModeTesting // Miscellaneous functions @@ -948,11 +958,10 @@ void tunnelgps() // --------------------------------------------------------------------------------------------- void doocxowarmup() { - unsigned long startWarmup = millis(); // we need a rough timer - // spend a few seconds/minutes here waiting for the OCXO to warm - // show countdown timer on OLED display + // Spend a few seconds/minutes here just waiting for the OCXO to warmup + // show countdown timer on OLED or LCD display // and report on either USB serial or Bluetooth serial - // Note: during warmup the GPSDO does not accept any commands + // Note: during OCXO warmup the GPSDO does not accept any commands uint16_t countdown = ocxo_warmup_time; while (countdown) { @@ -986,16 +995,31 @@ void doocxowarmup() disp.print(F("s")); #endif // LCD_ST7735 - #ifdef GPSDO_BLUETOOTH // print warming up message to either + #ifdef GPSDO_LCD_ST7789 + disp_st7789.fillScreen(ST77XX_BLACK); // display warmup message on LCD ST7735 + disp_st7789.setCursor(0, 0); + disp_st7789.print(F(Program_Name)); + disp_st7789.print(F(" - ")); + disp_st7789.print(F(Program_Version)); + disp_st7789.setCursor(0, 16); + disp_st7789.print(F("OCXO warming up")); + disp_st7789.setCursor(0, 24); + disp_st7789.print(F("Please wait")); + disp_st7789.setCursor(0, 32); + disp_st7789.print(countdown); + disp_st7789.print(F("s")); + #endif // LCD_ST7789 + + #ifdef GPSDO_BLUETOOTH // print warmup countdown message to either Serial2.println(); // Bluetooth serial xor USB serial - Serial2.print(F("Warming up ")); + Serial2.print(F("OCXO Warming up, ")); Serial2.print(countdown); - Serial2.println(F("s")); + Serial2.println(F("s remaining")); #else Serial.println(); - Serial.print(F("Warming up ")); + Serial.print(F("OCXO Warming up, ")); Serial.print(countdown); - Serial.println(F("s")); + Serial.println(F("s remaining")); #endif // BLUETOOTH // do nothing for 1s @@ -1050,6 +1074,18 @@ void docalibration() disp.print(F("Please wait")); #endif // LCD_ST7735 + #ifdef GPSDO_LCD_ST7789 + disp_st7789.fillScreen(ST77XX_BLACK); // display calibrating message on LCD ST7789 + disp_st7789.setCursor(0, 0); + disp_st7789.print(F(Program_Name)); + disp_st7789.print(F(" - ")); + disp_st7789.print(F(Program_Version)); + disp_st7789.setCursor(0, 16); + disp_st7789.print(F("Calibrating...")); + disp_st7789.setCursor(0, 24); + disp_st7789.print(F("Please wait")); + #endif // LCD_ST7789 + /* The calibration algorithm * The objective of the calibration is to find the approximate Vctl to obtain * 10MHz +/- 0.1Hz. @@ -1140,13 +1176,21 @@ void docalibration() #endif // BLUETOOTH #ifdef GPSDO_OLED - disp.clear(); + disp.clear(); // clear display and show program name and version again + disp.setCursor(0, 0); + disp.print(F(Program_Name)); + disp.print(F(" - ")); + disp.print(F(Program_Version)); #endif // OLED #ifdef GPSDO_LCD_ST7735 disp.fillScreen(ST7735_BLACK); #endif // LCD_ST7735 + #ifdef GPSDO_LCD_ST7789 + disp_st7789.fillScreen(ST77XX_BLACK); + #endif // LCD_ST7789 + yellow_led_state = 0; // turn off yellow LED (handled by 2Hz ISR) force_calibration_flag = false; // reset flag, calibration done } // end of GPSDO calibration routine @@ -1439,7 +1483,7 @@ void printGPSDOstats(Stream &Serialx) Serialx.print(avgftth,4); Serialx.println(F(" Hz")); - #ifdef GPSDO_BMP280_SPI + #if (defined (GPSDO_BMP280_SPI) || defined (GPSDO_BMP280_I2C)) // BMP280 measurements Serialx.println(); Serialx.print(F("BMP280 Temperature = ")); @@ -1572,7 +1616,7 @@ void displayscreen_OLED() // show GPSDO data on OLED display disp.print(F("/")); disp.print(year); - #ifdef GPSDO_BMP280_SPI + #if (defined (GPSDO_BMP280_SPI) || defined (GPSDO_BMP280_I2C)) // BMP280 temperature disp.setCursor(10, 6); disp.print(bmp280temp, 1); @@ -1640,7 +1684,7 @@ void displayscreen_LCD_ST7735() // show GPSDO data on LCD ST7735 display disp.setCursor(30, 72); disp.print(uptimestr); - #ifdef GPSDO_BMP280_SPI + #if (defined (GPSDO_BMP280_SPI) || defined (GPSDO_BMP280_I2C)) // BMP280 temperature disp.setCursor(90, 64); disp.print(F(" ")); @@ -1794,6 +1838,205 @@ void displayscreen_LCD_ST7735() // show GPSDO data on LCD ST7735 display } #endif // LCD_ST7735 +#ifdef GPSDO_LCD_ST7789 +void displayscreen_LCD_ST7789() // show GPSDO data on LCD ST7789 display + // we use font1 8x6 pix and font2 16x12 pix +{ + float tempfloat; + + // Latitude + disp_st7789.setCursor(0, 40); + disp_st7789.print(F("Lat: ")); + disp_st7789.print(GPSLat, 6); + // Longitude + disp_st7789.setCursor(0, 48); + disp_st7789.print(F("Lon: ")); + disp_st7789.print(GPSLon, 6); + // Altitude + disp_st7789.setCursor(0, 56); + disp_st7789.print(F("Alt: ")); + disp_st7789.print(GPSAlt); + disp_st7789.print(F("m ")); + //Satellites + disp_st7789.setCursor(90, 40); + disp_st7789.print(F("Sats: ")); + disp_st7789.print(GPSSats); + if (GPSSats < 10) disp_st7789.print(F(" ")); // clear possible digit when sats >= 10 + // HDOP + disp_st7789.setCursor(0, 64); + // choose HDOP or uptime + //disp_st7789.print(F("HDOP ")); + //tempfloat = ((float) GPSHdop / 100); + //disp_st7789.print(tempfloat); + disp_st7789.print(F("UpT: ")); + disp_st7789.print(updaysstr); + //disp_st7789.print(F(" ")); + disp_st7789.setCursor(30, 72); + disp_st7789.print(uptimestr); + + #if (defined (GPSDO_BMP280_SPI) || defined (GPSDO_BMP280_I2C)) + // BMP280 temperature + disp_st7789.setCursor(90, 64); + disp_st7789.print(F(" ")); + disp_st7789.print((char)247); + //disp_st7789.print((char)9); + disp_st7789.print(F("C: ")); + disp_st7789.print(bmp280temp, 1); + // BMP280 pressure + disp_st7789.setCursor(90, 72); + disp_st7789.print(F("hPa: ")); + disp_st7789.print(((bmp280pres+PressureOffset)/100), 1); + #endif // BMP280_SPI + + #ifdef GPSDO_VCC + disp_st7789.setCursor(90, 48); + // Vcc/2 is provided on pin PA0 + float Vcc = (float(avgVcc)/4096) * 3.3 * 2.0; + disp_st7789.print(F("5V0: ")); + disp_st7789.print(Vcc); + disp_st7789.print(F("V")); + #endif // VCC + + #ifdef GPSDO_VDD + // internal sensor Vref + disp_st7789.setCursor(90, 56); + float Vdd = (1.21 * 4096) / float(avgVdd); // from STM32F411CEU6 datasheet + disp_st7789.print(F("3V3: ")); + disp_st7789.print(Vdd); // Vdd = Vref on Black Pill + disp_st7789.print(F("V")); + #endif // VDD + + disp_st7789.setCursor(0, 80); // disp_st7789lay PWM/DAC value + #ifdef GPSDO_PWM_DAC + disp_st7789.print(F("PWM: ")); + disp_st7789.print(adjusted_PWM_output); + disp_st7789.print(F(trendstr)); + #else + disp_st7789.print(F("DAC: ")); + disp_st7789.print(adjusted_DAC_output); + disp_st7789.print(F(trendstr)); + #endif // PWM_DAC + + // display vref value + disp_st7789.setCursor(90, 80); // display vref value + float Vctlp = (float(avgpwmVctl)/4096) * 3.3; + disp_st7789.print(F("Vctl: ")); + disp_st7789.print(Vctlp); + disp_st7789.print(F("V")); + + // Display Headline and Version + disp_st7789.setTextColor(ST77XX_YELLOW, ST77XX_BLACK); + disp_st7789.setTextSize(2); + disp_st7789.setCursor(0, 0); + disp_st7789.print(F(" ")); + disp_st7789.print(F(Program_Name)); + // + disp_st7789.setTextSize(1); + disp_st7789.setCursor(115, 5); + disp_st7789.setTextColor(ST77XX_BLUE, ST77XX_BLACK); + disp_st7789.print(F(Program_Version)); + disp_st7789.setTextSize(2); + + // OCXO frequency + disp_st7789.setCursor(0, 19); + disp_st7789.setTextColor(ST77XX_YELLOW, ST77XX_BLACK); + + // disp_st7789lay 1s, 10s or 100s value depending on whether data is available + if (cbTen_full) { + if (cbTho_full) { // if we have data over 1000 seconds + if (avgftho < 10000000) { + disp_st7789.print(" "); + } + disp_st7789.print(avgftho, 3); // to 3 decimal places + } + else if (cbHun_full) { + if (avgfhun < 10000000) { + disp_st7789.print(" "); + } + disp_st7789.print(avgfhun, 2); // to 2 decimal places + disp_st7789.print(" "); + } + + else { // nope, only 10 seconds + if (avgften < 10000000) { + disp_st7789.print(" "); + } + disp_st7789.print(avgften, 1); // to 1 decimal place + disp_st7789.print(" "); + } + } + else { // we don't have any averages and print integer value + calcfreqint = calcfreq64; // convert to 32-bit integer + if (calcfreqint < 10000000) { + disp_st7789.print(" "); + } + disp_st7789.print(calcfreqint); // integer + disp_st7789.print(" "); // these are used for more exact disp_st7789aly + } + // due to limited space small character unit + disp_st7789.setTextSize(1); + disp_st7789.setCursor(144, 19); + // due to some unknown issue in printing the freq digits/unit we clear the section of the display first + disp_st7789.fillRect(144, 19, 15, 20, ST77XX_BLACK); + disp_st7789.print("Hz"); + + // clock and date + disp_st7789.setTextSize(2); + disp_st7789.setTextColor(ST77XX_RED, ST77XX_BLACK); + // Date + disp_st7789.setCursor(2, 94); + //disp_st7789.print(F("Date: ")); + disp_st7789.print(day); + disp_st7789.print(F(".")); + disp_st7789.print(month); + disp_st7789.print(F(".")); + disp_st7789.print(year); + + // Time + disp_st7789.setTextColor(ST77XX_GREEN, ST77XX_BLACK); + disp_st7789.setCursor(2, 113); + + if (hours < 10) + { + disp_st7789.print(F("0")); + } + + disp_st7789.print(hours); + disp_st7789.print(F(":")); + + if (mins < 10) + { + disp_st7789.print(F("0")); + } + + disp_st7789.print(mins); + disp_st7789.print(F(":")); + + if (secs < 10) + { + disp_st7789.print(F("0")); + } + + disp_st7789.print(secs); + disp_st7789.setTextColor(ST77XX_WHITE, ST77XX_BLACK); + disp_st7789.print(F(" UTC")); + + // reset all font stuff for normal display + disp_st7789.setTextSize(1); + disp_st7789.setTextColor(ST77XX_WHITE, ST77XX_BLACK); + +} +#endif // LCD_ST7789 + +#ifdef GPSDO_TM1637 + void displaytime_TM1637() { + int LEDtime = (hours * 100) + mins; + // Show UTC or local time on TM1637 4-digit LED display and blink colon at 1Hz + if ((secs%2) == 0) tm1637.showNumberDecEx(LEDtime, 0b11100000, true); + else tm1637.showNumberDec(LEDtime, true); + } +#endif // TM1637 + void uptimetostrings() { // translate uptime variables to strings uptimestr[0] = '0' + uphours / 10; @@ -1900,6 +2143,35 @@ void setup() disp.setTextSize(1); #endif // LCD_ST7735 + // Setup LCD SPI ST7789 display + #ifdef GPSDO_LCD_ST7789 + disp_st7789.init(240, 240, SPI_MODE3); // 1.3" 240x240 TFT LCD + delay(500); + disp_st7789.fillScreen(ST77XX_BLACK); + disp_st7789.setTextColor(ST77XX_YELLOW, ST77XX_BLACK); // + disp_st7789.setRotation(2); // 0..3 max, 1 = 90° = landscape + disp_st7789.setFont(); + disp_st7789.setTextSize(3); + // splash screen + disp_st7789.setCursor(40, 30); + disp_st7789.print(F(Program_Name)); + disp_st7789.setTextSize(1); + disp_st7789.setCursor(60, 65); + //disp_st7789.print(F(" - ")); + disp_st7789.setTextColor(ST77XX_WHITE, ST77XX_BLACK); + disp_st7789.print(F(Program_Version)); + disp_st7789.setTextColor(ST77XX_WHITE, ST77XX_BLACK); + disp_st7789.setTextSize(1); + #endif // LCD_ST7789 + + // Setup TM1637 4-digit LED module + #ifdef GPSDO_TM1637 + // Set the display brightness (0-7): + tm1637.setBrightness(5); + // Clear the display: + tm1637.clear(); + #endif // TM1637 + #ifdef GPSDO_UBX_CONFIG // Reconfigure the GPS receiver // first send the $PUBX configuration commands @@ -1919,48 +2191,46 @@ void setup() ubxconfig(); #endif // UBX_CONFIG - // Initialize I2C - Wire.begin(); - // try setting a higher I2C clock speed - Wire.setClock(400000L); - - #ifdef GPSDO_OLED + // Setup AHT10 / AHT20 temperature and humidity sensor module + #ifdef GPSDO_AHT10 // same code for AHT20 + Serial.println(F("Testing for presence of AHT10 or AHT20 Sensor on I2C bus")); + if (!aht.begin()) { + Serial.println(F("Could not find AHT10 or AHT20 sensor, check wiring")); + while (1) delay(10); + } + else Serial.println(F("AHT10 or AHT20 sensor found!")); + #endif // AHT10 - Note this seems to initialize the I2C bus interface + // Setup OLED I2C display - // Note that u8x8 library initializes I2C hardware interface - disp.setBusClock(400000L); // try to avoid display locking up - disp.begin(); - disp.setFont(u8x8_font_chroma48medium8_r); - disp.clear(); - disp.setCursor(0, 0); - disp.print(F(Program_Name)); - disp.print(F(" - ")); - disp.print(F(Program_Version)); + #ifdef GPSDO_OLED + // Note that u8x8 library initializes I2C hardware interface + // disp.setBusClock(400000L); // try to avoid display locking up + disp.begin(); + disp.setFont(u8x8_font_chroma48medium8_r); + disp.clear(); + disp.setCursor(0, 0); + disp.print(F(Program_Name)); + disp.print(F(" - ")); + disp.print(F(Program_Version)); #endif // OLED + // Setup INA219 current sensor module #ifdef GPSDO_INA219 - ina219.begin(&Wire3); // calibrates ina219 sensor Edit: start the sensor on the third I2C controller - Wire.setClock(400000L); + // By default the initialization will use the largest range (32V, 2A). However + // you can call a setCalibration function to change this range (see comments). + if (! ina219.begin()) { + Serial.println(F("Could not find INA219 sensor, check wiring")); + while (1) { delay(10); } + } + else Serial.println(F("INA219 sensor found!")); + // To use a slightly lower 32V, 1A range (higher precision on amps): + //ina219.setCalibration_32V_1A(); + // Or to use a lower 16V, 400mA range (higher precision on volts and amps): + //ina219.setCalibration_16V_400mA(); + ina219.setCalibration_32V_1A(); #endif // INA219 - - #ifdef GPSDO_MCP4725 - // Setup I2C DAC, read voltage on PB0 - adjusted_DAC_output = default_DAC_output; // initial DAC value - dac.begin(0x60); - // Output Vctl to DAC, but do not write to DAC EEPROM - dac.setVoltage(adjusted_DAC_output, false); // min=0 max=4096 so 2048 should be 1/2 Vdd = approx. 1.65V - #endif // MCP4725 - analogReadResolution(12); // make sure we read 12 bit values when we read from PB0 - Wire.setClock(400000L); - - #ifdef GPSDO_AHT10 - if (! aht.begin()) { - Serial.println("Could not find AHT10? Check wiring"); - while (1) delay(10); - } - Serial.println("AHT10 found"); - Wire.setClock(400000L); - #endif // AHT10 + analogReadResolution(12); // make sure we read 12 bit values when we read from any ADC analog channel // generate a 2kHz square wave on PB9 PWM pin, using Timer 4 channel 4 // PB9 is Timer 4 Channel 4 from Arduino_Core_STM32/variants/STM32F4xx/F411C(C-E)(U-Y)/PeripheralPins_BLACKPILL_F411CE.c @@ -1970,21 +2240,27 @@ void setup() adjusted_PWM_output = default_PWM_output; // initial PWM value analogWrite(VctlPWMOutputPin, adjusted_PWM_output); // 32767 for 16 bits -> 50% duty cycle so a square wave - #ifdef GPSDO_BMP280_SPI + #if (defined (GPSDO_BMP280_SPI) || defined (GPSDO_BMP280_I2C)) // Initialize BMP280 - if (!bmp.begin()) { - Serial.println(F("Could not find a valid BMP280 sensor, check wiring or " - "try a different address!")); - while (1) delay(10); - } - - // Default settings from datasheet. - bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, /* Operating Mode. */ - Adafruit_BMP280::SAMPLING_X2, /* Temp. oversampling */ - Adafruit_BMP280::SAMPLING_X16, /* Pressure oversampling */ - Adafruit_BMP280::FILTER_X16, /* Filtering. */ - Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */ - #endif // BMP280_SPI + Serial.println(F("Testing for presence of BMP280 Sensor on I2C bus")); + #ifdef GPSDO_BMP280_I2C // BMP280 on I2C bus requires specifying address + if (!bmp.begin(0x76,0x58)) { + #else + if (!bmp.begin()) { + #endif + Serial.println(F("Could not find BMP280 sensor, check wiring")); + while (1) delay(10); + } + else Serial.println(F("BMP280 sensor found!")); + + // Default settings from datasheet + bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, // Operating Mode + Adafruit_BMP280::SAMPLING_X2, // Temp. oversampling + Adafruit_BMP280::SAMPLING_X16, // Pressure oversampling + Adafruit_BMP280::FILTER_X16, // Filtering + Adafruit_BMP280::STANDBY_MS_500); // Standby time + + #endif // BMP280_SPI or BMP280_I2C Serial.println(F("GPSDO Starting")); Serial.println(); @@ -2020,23 +2296,17 @@ void setup() // Initialize movingAvg objects (note this allocates space on heap) and immediately read 1st value #ifdef GPSDO_VDD - avg_adcVdd.begin(); - adcVdd = analogRead(AVREF); - avgVdd = avg_adcVdd.reading(adcVdd); + avg_adcVdd.begin(); + adcVdd = analogRead(AVREF); + avgVdd = avg_adcVdd.reading(adcVdd); # endif // VDD #ifdef GPSDO_VCC - avg_adcVcc.begin(); - adcVcc = analogRead(VccDiv2InputPin); - avgVcc = avg_adcVcc.reading(adcVcc); + avg_adcVcc.begin(); + adcVcc = analogRead(VccDiv2InputPin); + avgVcc = avg_adcVcc.reading(adcVcc); # endif // VCC - #ifdef GPSDO_MCP4725 - avg_dacVctl.begin(); - dacVctl = analogRead(VctlInputPin); - avgdacVctl = avg_dacVctl.reading(dacVctl); - # endif // MCP4725 - avg_pwmVctl.begin(); pwmVctl = analogRead(VctlPWMInputPin); avgpwmVctl = avg_pwmVctl.reading(pwmVctl); @@ -2058,7 +2328,9 @@ void loop() if (tunnel_mode_flag) tunnelgps(); else if (gpsWaitFix(waitFixTime)) // wait up to waitFixTime seconds for fix, returns true if we have a fix - { + { + // if we have a GPS fix (implies we have a stable 1PPS pulse from the GPS) + #ifdef GPSDO_BLUETOOTH Serial2.println(); Serial2.println(); @@ -2090,39 +2362,33 @@ void loop() if (must_adjust_DAC && cbHun_full) // in principle just once every 429 seconds, and only if we have valid data { // use different algorithms for 12-bit I2C DAC and STM32 16-bit PWM DAC - #ifdef GPSDO_MCP4725 - adjustVctlDAC(); - #endif // MCP4725 #ifdef GPSDO_PWM_DAC - adjustVctlPWM(); + adjustVctlPWM(); #endif // PWM_DAC } - dacVctl = analogRead(VctlInputPin); // read the Vctl voltage output by the DAC - avgdacVctl = avg_dacVctl.reading(dacVctl); // average it - pwmVctl = analogRead(VctlPWMInputPin); // read the filtered Vctl voltage output by the PWM avgpwmVctl = avg_pwmVctl.reading(pwmVctl); // average it #ifdef GPSDO_VCC - adcVcc = analogRead(VccDiv2InputPin); // read Vcc - avgVcc = avg_adcVcc.reading(adcVcc); // average it + adcVcc = analogRead(VccDiv2InputPin); // read Vcc + avgVcc = avg_adcVcc.reading(adcVcc); // average it # endif // VCC #ifdef GPSDO_VDD - adcVdd = analogRead(AVREF); // Vdd is read internally as Vref - avgVdd = avg_adcVdd.reading(adcVdd); // average it + adcVdd = analogRead(AVREF); // Vdd is read internally as Vref + avgVdd = avg_adcVdd.reading(adcVdd); // average it #endif // VDD - #ifdef GPSDO_BMP280_SPI - bmp280temp = bmp.readTemperature(); // read bmp280 sensor, save values - bmp280pres = bmp.readPressure(); - bmp280alti = bmp.readAltitude(); - #endif // BMP280_SPI + #if (defined (GPSDO_BMP280_SPI) || defined (GPSDO_BMP280_I2C)) + bmp280temp = bmp.readTemperature(); // read bmp280 sensor, save values + bmp280pres = bmp.readPressure(); + bmp280alti = bmp.readAltitude(); + #endif // BMP280_SPI or BMP280_SPI #ifdef GPSDO_INA219 - ina219volt = ina219.busVoltage(); // read ina219 sensor, save values - ina219curr = ina219.shuntCurrent(); + ina219volt = ina219.getBusVoltage_V(); // read ina219 sensor, save values + ina219curr = ina219.getCurrent_mA(); #endif // INA219 uptimetostrings(); // get updaysstr and uptimestr @@ -2130,24 +2396,33 @@ void loop() yellow_led_state = 0; // turn off yellow LED #ifdef GPSDO_BLUETOOTH - printGPSDOstats(Serial2); // print stats to Bluetooth Serial + printGPSDOstats(Serial2); // print stats to Bluetooth Serial #else // xor - printGPSDOstats(Serial); // print stats to USB Serial + printGPSDOstats(Serial); // print stats to USB Serial #endif // BLUETOOTH #ifdef GPSDO_OLED - displayscreen_OLED(); + displayscreen_OLED(); #endif // OLED #ifdef GPSDO_LCD_ST7735 - displayscreen_LCD_ST7735(); + displayscreen_LCD_ST7735(); #endif // LCD_ST7735 + #ifdef GPSDO_LCD_ST7789 + displayscreen_LCD_ST7789(); + #endif // LCD_ST7789 + + #ifdef GPSDO_TM1637 + displaytime_TM1637(); + #endif // TM1637 + startGetFixmS = millis(); // have a fix, next thing that happens is checking for a fix, so restart timer } else // no GPS fix could be acquired for the last five seconds { - yellow_led_state = 1; // turn on yellow LED + // we don't have a GPS fix, so we consider that we don't have a stable 1PPS + yellow_led_state = 1; // turn on yellow LED to show something is not right #ifdef GPSDO_OLED disp.clear(); // display no fix message on OLED @@ -2173,6 +2448,18 @@ void loop() disp.print(F("s")); #endif // LCD_ST7735 + #ifdef GPSDO_LCD_ST7789 + disp_st7789.fillScreen(ST77XX_BLACK); // display no fix message on ST7735 LCD + disp_st7789.setCursor(0, 0); + disp_st7789.print(F(Program_Name)); + disp_st7789.print(F(" - ")); + disp_st7789.print(F(Program_Version)); + disp_st7789.setCursor(0, 8); + disp_st7789.print(F("Wait fix ")); + disp_st7789.print( (millis() - startGetFixmS) / 1000 ); + disp_st7789.print(F("s")); + #endif // LCD_ST7789 + #ifdef GPSDO_BLUETOOTH // print no fix message to either Serial2.println(); // Bluetooth serial or USB serial Serial2.print(F("Waiting for GPS Fix ")); @@ -2185,7 +2472,9 @@ void loop() Serial.println(F("s")); #endif // BLUETOOTH - // no fix, raise flush_ring_buffers_flag + // no fix or fix lost, we must flush the ring buffers, + // so raise flush_ring_buffers_flag flush_ring_buffers_flag = true; } + } // end of loop()