Search code examples
c++arduinoserial-portuart

Serial Communication on Arduino Nano IoT 33


I'm having trouble since moving from an Uno to the Nano 33 IoT unit. I have read up on a lot of info with regards to this specific topic and still I pretty confused as I'm quite use to working with the Software Serial that's not available on the Nano 33. According to the: https://github.com/ostaquet/Arduino-Nano-33-IoT-Ultimate-Guide Guide using an addition port for serial as I'm all ready using Serial1 TX Pin 0, and RX Pin 1 my Sigfox unit: https://yadom.fr/carte-breakout-sfm10r1.html workes fine. The trouble is with my gps. If i swap the 2 around the GPS works fine and the Sigfox unit doesn't...

#include <TinyGPS++.h>
#include <Arduino.h>
#include "wiring_private.h"
static const uint32_t GPSBaud = 9600;
#define DEBUG 1
TinyGPSPlus gps;
uint8_t msg[12];

Uart mySerial (&sercom0, 5, 6, SERCOM_RX_PAD_1, UART_TX_PAD_2);

// Attach the interrupt handler to the SERCOM
void SERCOM0_Handler()
{
    mySerial.IrqHandler();
}


void setup() {
  pinMode(LED_BUILTIN, OUTPUT);      // set LED pin as output
  digitalWrite(LED_BUILTIN, LOW);    // switch off LED pin
  pinPeripheral(5, PIO_SERCOM);
  pinPeripheral(6, PIO_SERCOM);

   if(DEBUG){
    Serial.begin(9600);
  }
  
  mySerial.begin(GPSBaud);
  Serial1.begin(9600);
  delay(100);
  getID();
  delay(100);
  getPAC();
}

void loop()
{
  msg[0]=0xC0;
  msg[1]=0xFF;
  msg[2]=0xEE;

  sendMessage(msg, 3);
  
  printInt(gps.satellites.value(), gps.satellites.isValid(), 5);
  printFloat(gps.hdop.hdop(), gps.hdop.isValid(), 6, 1);
  printFloat(gps.location.lat(), gps.location.isValid(), 11, 6);
  printFloat(gps.location.lng(), gps.location.isValid(), 12, 6);
  printInt(gps.location.age(), gps.location.isValid(), 5);
  printDateTime(gps.date, gps.time);
  printFloat(gps.altitude.meters(), gps.altitude.isValid(), 7, 2);
  printFloat(gps.course.deg(), gps.course.isValid(), 7, 2);
  printFloat(gps.speed.kmph(), gps.speed.isValid(), 6, 2);
  printStr(gps.course.isValid() ? TinyGPSPlus::cardinal(gps.course.deg()) : "*** ", 6);

  printInt(gps.charsProcessed(), true, 6);
  printInt(gps.sentencesWithFix(), true, 10);
  printInt(gps.failedChecksum(), true, 9);
  Serial.println();

    delay(120000);

  if (millis() > 5000 && gps.charsProcessed() < 10)
    Serial.println(F("No GPS data received: check wiring"));
}

void blink(){
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);    
}

//Get Sigfox ID
String getID(){
  String id = "";
  char output;

  Serial1.print("AT$I=10\r");
  while (!Serial1.available()){
     blink();
  }

  while(Serial1.available()){
    output = Serial1.read();
    id += output;
    delay(10);
  }

  if(DEBUG){
    Serial.println("Sigfox Device ID: ");
    Serial.println(id);
  }

  return id;
}

//Get PAC number
String getPAC(){
  String pac = "";
  char output;

  Serial1.print("AT$I=11\r");
  while (!Serial1.available()){
     blink();
  }

  while(Serial1.available()){
    output = Serial1.read();
    pac += output;
    delay(10);
  }

  if(DEBUG){
    Serial.println("PAC number: ");
    Serial.println(pac);
  }

  return pac;
}

//Send Sigfox Message
void sendMessage(uint8_t msg[], int size)
{
  Serial.println("Sigfox Start");

  String status = "";
  String hexChar = "";
  String sigfoxCommand = "";
  char output;

  sigfoxCommand += "AT$SF=";

  for (int i = 0; i < size; i++)
  {
    hexChar = String(msg[i], HEX);

    //padding
    if (hexChar.length() == 1)
    {
      hexChar = "0" + hexChar;
    }

    sigfoxCommand += hexChar;
  }

  Serial.println("Sending Sigfox Message...");
  Serial.println(sigfoxCommand);
  Serial1.println(sigfoxCommand);

  while (!Serial1.available())
  {
    Serial.println("Waiting for Sigfox Response");
    delay(7000);
  }

  while (Serial1.available())
  {
    output = (char)Serial1.read();
    status += output;
    delay(10);
  }

  Serial.println();
  Serial.print("Sigfox Status \t");
  Serial.println(status);
}


// This custom version of delay() ensures that the gps object
// is being "fed".
static void smartDelay(unsigned long ms)
{
  unsigned long start = millis();
  do 
  {
    while (mySerial.available())
      gps.encode(mySerial.read());
  } while (millis() - start < ms);
}

static void printFloat(float val, bool valid, int len, int prec)
{
  if (!valid)
  {
    while (len-- > 1)
      Serial.print('*');
    Serial.print(' ');
  }
  else
  {
    Serial.print(val, prec);
    int vi = abs((int)val);
    int flen = prec + (val < 0.0 ? 2 : 1); // . and -
    flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
    for (int i=flen; i<len; ++i)
      Serial.print(' ');
  }
  smartDelay(0);
}

static void printInt(unsigned long val, bool valid, int len)
{
  char sz[32] = "*****************";
  if (valid)
    sprintf(sz, "%ld", val);
  sz[len] = 0;
  for (int i=strlen(sz); i<len; ++i)
    sz[i] = ' ';
  if (len > 0) 
    sz[len-1] = ' ';
  Serial.print(sz);
  smartDelay(0);
}

static void printDateTime(TinyGPSDate &d, TinyGPSTime &t)
{
  if (!d.isValid())
  {
    Serial.print(F("********** "));
  }
  else
  {
    char sz[32];
    sprintf(sz, "%02d/%02d/%02d ", d.month(), d.day(), d.year());
    Serial.print(sz);
  }
  
  if (!t.isValid())
  {
    Serial.print(F("******** "));
  }
  else
  {
    char sz[32];
    sprintf(sz, "%02d:%02d:%02d ", t.hour(), t.minute(), t.second());
    Serial.print(sz);
  }

  printInt(d.age(), d.isValid(), 5);
  smartDelay(0);
}

static void printStr(const char *str, int len)
{
  int slen = strlen(str);
  for (int i=0; i<len; ++i)
    Serial.print(i<slen ? str[i] : ' ');
  smartDelay(0);
}

My problem is hence with the additional port creating via this section:

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

Uart mySerial (&sercom0, 5, 6, SERCOM_RX_PAD_1, UART_TX_PAD_0);

// Attach the interrupt handler to the SERCOM
void SERCOM0_Handler()
{
    mySerial.IrqHandler();
}

void setup() {
  // Reassign pins 5 and 6 to SERCOM alt
  pinPeripheral(5, PIO_SERCOM_ALT);
  pinPeripheral(6, PIO_SERCOM_ALT);

  // Start my new hardware serial
  mySerial.begin(9600);
}

void loop() {
  // Do something with mySerial...
}

On the Nano I have my TX on Nano Pin 6 (As it starts at ) and RX on Pin 7 "6" as it starts on 0....

It's swapped as to make RX and TX talk to each other on the board Where RX on the GPS = TX on the Nano, and TX on the GPS = RX on the Nano.

Am I using the wrong pins? AS the GPS doesn't want to respond with pin 5 & 6 pins at all...

enter image description here

The Lights blink on the gps so there's power, and if I swap the Gps with the Sigfox unit The gps works and the Sigfox unit then doesn't.

Am I using the wrong pins on the Nano Board? Please Help....


Solution

  • SERCOM0 with pins 5 and 6 are a good choice for additional Serial interface on Nano 33 IoT. The variant.cpp file has

     +------------+------------------+--------+---------+---------+
     | Pin number | NANO  Board pin  |  PIN   | SERCOMx | SERCOMx |
     |            |                  |        | (x/PAD) | (x/PAD) |
     +------------+------------------+--------+---------+---------+
     | 5          | ~D5              |  PA05  |         |   0/01  |
     | 6          | ~D6              |  PA04  |         |   0/00  |
    

    So the instantiation should be

      Uart mySerial (&sercom0, 5, 6, SERCOM_RX_PAD_1, UART_TX_PAD_0);
    

    you have UART_TX_PAD_2

    Pin 5 is RX and pin 6 is TX.


    The

    pinPeripheral(5, PIO_SERCOM_ALT);
    pinPeripheral(6, PIO_SERCOM_ALT);
    

    commands should be after mySerial.begin, because begin does

    pinPeripheral(uc_pinRX, g_APinDescription[uc_pinRX].ulPinType);
    

    but .ulPinType is not PIO_SERCOM_ALT.