GrumpyOldPizza / ArduinoCore-stm32l0

Arduino Core for STM32L0
125 stars 67 forks source link

GNSS basic control passthru, no stream from GPS #157

Open hallard opened 4 years ago

hallard commented 4 years ago

I'm trying to get working a GNSS passthru code to be able to connect UBLOX U-Center to Gnat board to play with GPS.

Unfortunately, I never get it to work, so I tried something very simple without any success either.

Even if sample sketches using gps.ino (initialized with GNSS.begin(GNSS.MODE_NMEA, GNSS.RATE_1HZ) ) with this board is working perfectly fine, when I'm using my sketch, I'm just trying to get RAW output from the GPS such as NMEA strings, I got nothing even if I power the GPS.

I may forget something basic, but don't know what, this is the simple sketch I'm using.

#include <STM32L0.h>

#define SerialMon  Serial
#define SerialGNSS Serial1

// CAM M8Q GNSS configuration
#define GNSS_ENABLE  (5u)  // enable for GNSS 3.0 V LDO
#define GNSS_PPS     (4u)  // 1 Hz fix pulse
#define GNSS_BACKUP  A0  

volatile bool pps_irq;

void int_pps(void) {
  pps_irq = true;
}

void setup()
{

  // Start communication
  SerialMon.begin(9600);
  SerialGNSS.begin(9600);

  // Wait for USB serial mounted in 5s max
  while (!SerialMon && millis()<5000) {
    delay(10);
  }

  SerialMon.println("\r\n\r\n*** Starting firmware GNSS Passtrhu ***");
  SerialMon.println("GNSS Connected pins");
  SerialMon.print("ENABLE=");  SerialMon.print(GNSS_ENABLE);
  SerialMon.print("  BACKUP=");SerialMon.print(GNSS_BACKUP);
  SerialMon.print("  PPS=");   SerialMon.println(GNSS_PPS);

  // Set GNSS state to active
  pinMode(GNSS_ENABLE, OUTPUT);
  digitalWrite(GNSS_ENABLE, HIGH);

  pinMode(GNSS_BACKUP, OUTPUT);
  digitalWrite(GNSS_BACKUP, HIGH);

  pinMode(GNSS_PPS, INPUT);
  attachInterrupt(GNSS_PPS, int_pps, FALLING);  

  SerialMon.println("Setup done!");
}

// Forward every message to the other serial
void loop()
{
  while (SerialMon.available()) {
    SerialGNSS.write(SerialMon.read());
  }

  while (SerialGNSS.available()) {
    SerialMon.write(SerialGNSS.read());
  }

  // Got PPS (each second once fixed)
  if (pps_irq){
    pps_irq = false;
    SerialMon.println("Got PPS");
  }
}

And of course the output, nothing on it don't get even any IRQ fix, what am I missing ?

15:14:13.512 -> 
15:14:13.512 -> *** Starting firmware GNSS Passtrhu ***
15:14:13.512 -> GNSS Connected pins
15:14:13.512 -> ENABLE=5  BACKUP=16  PPS=4
15:14:13.512 -> Setup done!
hallard commented 4 years ago

Self answering after digging into GNSS library and done some copy/paste

If I initialize GNSS pins with arduino like number (see function gnssBegin_Arduino()) it does not works, but if I'm doing with STM32 like with gnssBegin_STM32() it works, may be a pin state that differs (because pin mapping number are correct, it's very strange.

See below

#include <STM32L0.h>
#include "wiring_private.h"

#define SerialMon  Serial
#define SerialGNSS Serial1

// CAM M8Q GNSS configuration (Arduino pin number mode)
#define GNSS_ENABLE  (5u)  // enable for GNSS 3.0 V LDO
#define GNSS_PPS     (4u)  // 1 Hz fix pulse
#define GNSS_BACKUP  A0  

// CAM M8Q GNSS configuration (STM32 framework pin number mode)
uint16_t stm32_enable_pin = g_APinDescription[GNSS_ENABLE].pin;
uint16_t stm32_pps_pin    = g_APinDescription[GNSS_PPS].pin;
uint16_t stm32_backup_pin = g_APinDescription[GNSS_BACKUP].pin;
volatile bool pps_irq;

void int_pps(void) {
  pps_irq = true;
}

void gnssBegin_Arduino()
{
  pinMode(GNSS_BACKUP, OUTPUT);
  digitalWrite(GNSS_BACKUP, HIGH);

  // Set GNSS state to active
  pinMode(GNSS_ENABLE, OUTPUT);
  digitalWrite(GNSS_ENABLE, HIGH);

  pinMode(GNSS_PPS, INPUT);
  attachInterrupt(GNSS_PPS, int_pps, FALLING);  
}

void gnssBegin_STM32()
{
  stm32l0_gpio_pin_configure(stm32_backup_pin, (STM32L0_GPIO_PARK_NONE | STM32L0_GPIO_PUPD_PULLUP | STM32L0_GPIO_OSPEED_LOW | STM32L0_GPIO_OTYPE_PUSHPULL | STM32L0_GPIO_MODE_OUTPUT));
  stm32l0_gpio_pin_write(stm32_backup_pin, 1);

  stm32l0_gpio_pin_configure(stm32_enable_pin, (STM32L0_GPIO_PARK_NONE | STM32L0_GPIO_PUPD_PULLUP | STM32L0_GPIO_OSPEED_LOW | STM32L0_GPIO_OTYPE_PUSHPULL | STM32L0_GPIO_MODE_OUTPUT));
  stm32l0_gpio_pin_write(stm32_enable_pin, 1);

  stm32l0_gpio_pin_configure(stm32_pps_pin, (STM32L0_GPIO_PARK_NONE | STM32L0_GPIO_PUPD_PULLDOWN | STM32L0_GPIO_OSPEED_HIGH | STM32L0_GPIO_OTYPE_PUSHPULL | STM32L0_GPIO_MODE_INPUT));
  stm32l0_exti_attach(stm32_pps_pin, STM32L0_EXTI_CONTROL_EDGE_FALLING | STM32L0_EXTI_CONTROL_PRIORITY_CRITICAL, (stm32l0_exti_callback_t)&int_pps, (void*)NULL);
}

void setup()
{
  // Start communication
  SerialMon.begin(9600);

  // Wait for USB serial mounted in 5s max
  while (!SerialMon && millis()<5000) {
    delay(10);
  }

  SerialMon.println("\r\n\r\n*** Starting firmware GNSS Passtrhu ***");
  SerialMon.println("GNSS Arduino/STM32 Connected pins");
  SerialMon.print("ENABLE=");  SerialMon.print(GNSS_ENABLE);
  SerialMon.print("/");  SerialMon.print(stm32_enable_pin);
  SerialMon.print("  BACKUP=");SerialMon.print(GNSS_BACKUP);
  SerialMon.print("/");  SerialMon.print(stm32_backup_pin);
  SerialMon.print("  PPS=");   SerialMon.print(GNSS_PPS);
  SerialMon.print("/");  SerialMon.println(stm32_pps_pin);

  gnssBegin_STM32();
  SerialGNSS.begin(9600);

  SerialMon.println("Setup done!");
}

// Forward every message to the other serial
void loop()
{
  while (SerialMon.available()) {
    SerialGNSS.write(SerialMon.read());
  }

  while (SerialGNSS.available()) {
    SerialMon.write(SerialGNSS.read());
  }

  // Got PPS (each second once fixed)
  if (pps_irq){
    pps_irq = false;
    //SerialMon.println("Got PPS");
  }
}

Interesting, isn't it :-)

SloMusti commented 4 years ago

@hallard I am observing the same thing, however this does work on the latest release, but not on the master,

hallard commented 4 years ago

Correct, I'm using master also and was working before.

SloMusti commented 4 years ago

@hallard Have found the problem and the solution. See https://github.com/IRNAS/ArduinoCore-stm32l0/commit/6b5c14cb3475e990b217c5a8347950c04bca896b

There is a problem with custom board definitions as the DMA channels and/or Timers have changed and this affects serial.

hallard commented 4 years ago

@SloMusti awesome, I need to report back, the $1 000 000 question is why it has been changed in variant, surely @GrumpyOldPizza had a good reason which could be fine to know :-)

GrumpyOldPizza commented 4 years ago

Interesting.

The DMA assignments were changed to support async SPI (so that you can transfer in the background to say a e-Paper thingy).

The change in DMA assignments does not make any difference. The UART driver works with and without DMA on RX and TX. It's just that STM32L0 really wants DMA on RX to avoid missing characters at higher speeds.

Please do not hack around trying to use the GNSS UART directly. The uBLOX parts are painfully fragile if you wanna get low power correctly.

If you want to send a command, you could use the same logic as the GNSS class does (for AssistNow). If you want to use the GNSS in passthrou, then yes, you have to mess with the LDO/BACKUP pins directly bypassing Arduino, as those GPIOs have been blocked off.

SloMusti commented 4 years ago

@GrumpyOldPizza thank you for the reply. The passthrough option is what we use simply to validate GPS is alive in testing, not for any real use. GNSS library is used in that case on my end always.

SloMusti commented 4 years ago

The interesting change has been that the order in which Serial and Serial1 are initialized mattered, until we have fixed our custom variant.