Skip to content

11. Input Devices

Assignments Overview

Here is the list of individual assignments given by the instructors. As for the Group Assignment, please see the Group Assignment page on the FabLab Kannai website:

  Measure something: add a sensor to a microcontroller board                              
  that you have designed and read it.

Input Devices I Have Chosen

In the final project, I don’t have a plan to use any input device. I would like to make it clear at this point of time that the input device tests I would make had nothing to do with my final project.

However, looking back at my past experience in the interactions with the field workers for international development and my ongoing activities in the daily life, I understood that there would be many possibilities to use the input devices in the following cases:

  • Optical/Sonar Sensors for Vehicle Protection: While I was interacting with a car salesman on the purchase of a new car recently, I came to know that it had become their responsibility to brief their customers about the safety arrangements already installed in the cars they were selling. The most peculiar examples are the optical sensors in the front and the sonar sensors in the rear. The front optical sensors detect the car in front of us or any other obstacle getting near to our car so that the car could automatically slow down or be braked. It prohibits the drivers from sudden start if there is a wall or any other obstacle in front of it. The sonar sensors in the rear whill help the driver to avoid hitting the poles or other cars nearby in the parking lot.

  • GPS for Tracking System: Although I dropped an idea for adding a GPS tracking system to my final project, it could still be useful to locate the posision of the valuables as well as the small children.

  • Image Sensors for Flood Early Warning: These sensors could be desparately wanted in the hilly areas which are vulnerable to the flash floods. When I was stationed in Bhutan, I saw many irrigation experts discussing the benefit of installing the cameras in the upstream remote areas so that they could keep an eye on the fluctuation of the water level of the target river. In most cases there are very few population in the upstream of the watersheds in Bhutan and villagers did not understand how come the flash flood hit their settlements all of a sudden. If we could install a camera and a data transmitting device, we could expect the heavy rainfall in the upper hills and send out an early flood warning to the dwellers downstream, ultimately avoiding such tragic events as reported in the following article: Kuensel, July 22nd, 2023

After a few considerations, for this week’s individual assignment, I decided to work on optical sensors and GPS module.

Laser Ranging Sensor/Time-of-Flight Distance Sensor

alt text

VL53L0/1XV2 Laser Ranging Sensor Time-of-Flight

Operating Voltage: 2.6V-3.5V                                    
Power Consumption: 20 mW @10Hz              
Measurement Range: 40 mm ~ 4,000mm                           
Resolution: ±1 mm                                   
Light Source Class 1 940nm VCSEL                          
Interface Type: I2C

VL53L0X is a high speed, high accuracy, and long range distance sensor based on VL53L0X. The VL53L0X is a new generation Time-of-Flight (ToF) laser-ranging module housed in the smallest package on the market today, providing accurate distance measurement whatever the target reflectances, unlike conventional technologies. It can measure absolute distances up to 2m, […]. The VL53L0X’s 940 nm VCSEL emitter (VerticalCavity Surface-Emitting Laser), is totally invisible to the human eye, coupled with internal physical infrared filters, it enables longer ranging distances, higher immunity to ambient light, and better robustness to cover glass optical crosstalk. (Excerpt from Sharvi Electronics)

GPS Module

GT-U7

alt text

Operating voltage: 3.6V-5V (or direct usb power supply)                  
Operating baud rate: 9600 (can be modified)                              
Onboard E2PROM can save parameter data
NEMA output format is compatible with NEO-6M
Size: 27.6mm * 26.6mm can                                                
Compatible Devices  STM32, 51 Microcontroller, Arduino UNO R3
  • Note: Please use the GT-U7 GPS module in an open place, the LED will flash after the satellite signal is found. Bad weather and indoor use will affect the accuracy of positioning

  • GPS baud needs to be set to 9600 instead of 4800; PPS pin is not needed unless using the GPS to drive a hardware high precision clock; GT-U7 main module GPS module using the original UBLOX 7th generation chip, Software is compatible with NEO-6M. GT-U7 module, with high sensitivity, low power consumption, miniaturization, its extremely high tracking sensitivity greatly expanded its positioning of the coverage

  • With a USB interface, you can directly use the phone data cable on the computer point of view positioning effect; With IPEX antenna interface, the default distribution of active antenna, can be quickly positioned

  • USB directly connected to the computer, That is, with the host computer-owned serial port function, no need for external serial module, send IPX interface active antenna (Excerpt from the Amazon)


Problems on ToF Distance Sensor - My Unsuccess Story

In fact, I spent too much time struggling the way to upload the sketches via Arduino IDE. Even one day before the global review session on Wednesday, April 17, I have never succeeded in uploading even once for the VL53L0/1XV2 ToF distance sensor.

Because my board had the I2C port with four pins, I first tried to connect with jumper wires my board and VL53L0/1XV2 board as shown in the following snapshot.

alt text

Device VL53L0/1XV2X Board
3V3 VIN
GND GND
SDA SDA
SCL SCL

Once the board connection was ready, I opened the Arduino IDE and called the Board Manager to sellect “XIAO_ESP32C3”. The COM15 was automatically assigned as the serial port. Next I went to Library Manager by moving to: Sketch > Include Libraries > Manage Libraries > Type “VL53L0” for installing. Next I went to: File > Examples > VL53L0X, and selected “Continuous” to open a sample sketch.

So far so good. However, once I started compiling, I came across the first error message “Compilation error: VL53L0X.h: No such file or directory”.

alt text

Then as per advised by the instructor, I changed line 8 #include to “VL53L0X.h” and retried. Then I came across the second error message “Compilation error: exit status 1”.

alt text

Then, I went to Polou’s VL53L0X-Arduino Library and directly downloaded the ZIP file of the libraries. Next I expanded the ZIP file and copied the cpp and hex files to the sample sketch folder. Once the library files were pasted, I opened the “Continuous” sample sketch file again.

alt text

alt text

Now the compliling was successful. However, when I proceeded to uploading, I faced the next error, “Failed uploading: uploading error: exit status 2”.

alt text

Actually, this error was chronic and kept annoying me for a few days. I once wondered if there was something wrong with my board, and took the Xiao ESP32C3 chip out of my board and directly connected it to the ToF distance sensor on the breadboard. But it was not a solution at all.

alt text

I wondered what if I import the VL53L1X library instead of VL53L0X. After following the same trial-and-error steps described above for VL32L0X, I came to face the same error message and failed in connecting to the serial monitor.

alt text

Hoping to rectify the problem, I even tried to replace the Xiao ESP32C3 with Seeed Xiao RP2040, which didn’t solve the problem either.

Hold-Press the Boot Button?: As a matter of course, I searched for the solution on the Internet. Most of them were suggesting the following actions: When the program starts printing “Connecting....”, just hold-press the “Boot” button on my microcontroller. Although I thought that it looked so primitive, I tried this again and again, only to see none of my efforts was successful.

What If I Change the Computer?: On Tuesday, April 16, I downloaded the Arduino IDE to my old laptop and tried to see if it could go well. Downloading fine. Libraries for VL53L0X and VL53L1X were successful. Compilation was also successful even without copying the cpp and hex files to the sample sketch folders. Everything went so smoothly. However, when it came to uploading, I faced the familiar error, “Failed uploading: uploading error: exit status 2”. I tried both Xiao ESP32C3 and RP4020, tried rebooting, tried reconnection of the USB cable, anything I could think of.

As of 4pm JST, Wednesday, April 17, I have not found the way out.


Revenge with the GPS Module

For change of air, I moved to the GPS module. As the above specification indicated, GT-U7 GPS module could go with the Arduino UNO R3. Therefore, I left the Xiao ESP32C2 and RP2040 for the Arduino board.

Following the Maker Tutor’s “OPEN-SMART GT-7U GPS Module with Arduino”, I set up the wire connection and imported the library from TinyGPSPlus GPS Arduino Library.

Arduino GT-U7 Board
5V VCC
GND GND
Pin 3 RX
Pin 4 TX

alt text

As for the import of the TinyGPSPlus Library, I went through the trial-and-error process very similar to the case for the ToF distance sensor. The following is the code that I ran for the Basic Example.

#include "TinyGPSPlus.h"                                                        
/* 
This sample sketch should be the first you try out when you are testing a TinyGPSPlus      
(TinyGPSPlus) installation.  In normal use, you feed TinyGPSPlus objects characters from 
a serial NMEA GPS device, but this example uses static strings for simplicity.
*/

// A sample NMEA stream.
const char *gpsStream =                                  
  "$GPRMC,045103.000,A,3014.1984,N,09749.2872,W,0.67,161.46,030913,,,A*7C\r\n"
  "$GPGGA,045104.000,3014.1985,N,09749.2873,W,1,09,1.2,211.6,M,-22.5,M,,0000*62\r\n"
  "$GPRMC,045200.000,A,3014.3820,N,09748.9514,W,36.88,65.02,030913,,,A*77\r\n"
  "$GPGGA,045201.000,3014.3864,N,09748.9411,W,1,10,1.2,200.8,M,-22.5,M,,0000*6C\r\n" 
  "$GPRMC,045251.000,A,3014.4275,N,09749.0626,W,0.51,217.94,030913,,,A*7D\r\n" 
  "$GPGGA,045252.000,3014.4273,N,09749.0628,W,1,09,1.3,206.9,M,-22.5,M,,0000*6F\r\n";

// The TinyGPSPlus object   
TinyGPSPlus gps;  
void setup()
{
  Serial.begin(9600);

  Serial.println(F("BasicExample.ino"));
  Serial.println(F("Basic demonstration of TinyGPSPlus (no device needed)"));
  Serial.print(F("Testing TinyGPSPlus library v. ")); Serial.println(TinyGPSPlus::libraryVersion());
  Serial.println(F("by Mikal Hart"));
  Serial.println();

  while (*gpsStream)
    if (gps.encode(*gpsStream++))
        displayInfo();

  Serial.println();    
  Serial.println(F("Done."));
}

void loop()
{
}

void displayInfo()
{
  Serial.print(F("Location: ")); 
  if (gps.location.isValid())
  {
    Serial.print(gps.location.lat(), 6);
    Serial.print(F(","));
    Serial.print(gps.location.lng(), 6);
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.print(F("  Date/Time: "));
  if (gps.date.isValid())
  {
    Serial.print(gps.date.month());
    Serial.print(F("/"));
    Serial.print(gps.date.day());
    Serial.print(F("/"));
    Serial.print(gps.date.year());
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.print(F(" "));
  if (gps.time.isValid())
  {
    if (gps.time.hour() < 10) Serial.print(F("0"));
    Serial.print(gps.time.hour());
    Serial.print(F(":"));
    if (gps.time.minute() < 10) Serial.print(F("0"));
    Serial.print(gps.time.minute());
    Serial.print(F(":"));
    if (gps.time.second() < 10) Serial.print(F("0"));
    Serial.print(gps.time.second());
    Serial.print(F("."));
    if (gps.time.centisecond() < 10) Serial.print(F("0"));
    Serial.print(gps.time.centisecond());
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.println();
}

Problem 1: Incorrect Date/Time Stamps I put up the two test run results herewith. There seem to be something wrong with the date and time recorded on the serial monitor. I haven’t figured out how to put the real date and time in the program.

alt text

Problem 2: Invalid Sketch File Name Another problem was that as I kept running the above code or any other sample sketch, I suddenly started facing the following error message of “Invalid Sketch File Name” many times and couldn’t finish compiling all the sample sketches. As a result, I lost a clue to replicate even one single case of serial communication with my laptop.

alt text

Problem 3: Another Laptop, but Incorrect Date/Time Stamps Persist About the GPS sensor, I also decided to do it with another laptop. It went more smoothly than I had expected. I could download the Libraries for TinyGPS, TinyGPSPlus and TinyGPSPlusPlus from the Libary Manager. Whenever I imported the sample sketches, they could import the library files as well. No need for copy-and-pasting the cdd and hex files to each sample sketch folder.

alt text

alt text

I started with the same Basic Example sketch as described above in my first trial. Compiling and uploading went smoothly. However, I faced the same problem described in the Problem 1 above: Incorrect date and time in the serial monitor.

alt text

Problem 4: Is the Serial Location Data Correct? Now I became skeptical about the test results with the GPS module and my laptop. In order to see if I could get a different result, I brought my laptop and GPS module out to the nearest shrine and ran the same code. I found that there was another problem: Incorrect location data. Wherever I go, I get almost the same location data and date/time stamps.

alt text alt text

alt text

Problem 5: In/Out Pins Working? I started wondering if the GPS sensor was really functioning. Therefore, I called for another sample sketch “Device Example” as a sample with specific references to RX pin and TX pin. The following is the code I imported. Please note that I faced the same “Invalid Sketch File Name” problem described in the Proble 2 above. However, I could rectify the problem by renaming the cpp and hex files: “TinyGPS++.cpp” -> “TinyGPSPlusPlus.cpp” and “TinyGPS++.h” to “TinyGPSPlusPlus.h”. Of course I corrected all the file names in the code accordingly.

#include "TinyGPSPlus.h"
#include "SoftwareSerial.h"
/*
   This sample sketch demonstrates the normal use of a TinyGPSPlus (TinyGPSPlus) object.
   It requires the use of SoftwareSerial, and assumes that you have a
   4800-baud serial GPS device hooked up on pins 4(rx) and 3(tx).
*/
static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 4800;

// The TinyGPSPlus object
TinyGPSPlus gps;

// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);

void setup()
{
  Serial.begin(115200);
  ss.begin(GPSBaud);

  Serial.println(F("DeviceExample.ino"));
  Serial.println(F("A simple demonstration of TinyGPSPlus with an attached GPS module"));
  Serial.print(F("Testing TinyGPSPlus library v. ")); Serial.println(TinyGPSPlus::libraryVersion());
  Serial.println(F("by Mikal Hart"));
  Serial.println();
}

void loop()
{
  // This sketch displays information every time a new sentence is correctly encoded.
  while (ss.available() > 0)
    if (gps.encode(ss.read()))
      displayInfo();

  if (millis() > 5000 && gps.charsProcessed() < 10)
  {
    Serial.println(F("No GPS detected: check wiring."));
    while(true);
  }
}

void displayInfo()
{
  Serial.print(F("Location: ")); 
  if (gps.location.isValid())
  {
    Serial.print(gps.location.lat(), 6);
    Serial.print(F(","));
    Serial.print(gps.location.lng(), 6);
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.print(F("  Date/Time: "));
  if (gps.date.isValid())
  {
    Serial.print(gps.date.month());
    Serial.print(F("/"));
    Serial.print(gps.date.day());
    Serial.print(F("/"));
    Serial.print(gps.date.year());
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.print(F(" "));
  if (gps.time.isValid())
  {
    if (gps.time.hour() < 10) Serial.print(F("0"));
    Serial.print(gps.time.hour());
    Serial.print(F(":"));
    if (gps.time.minute() < 10) Serial.print(F("0"));
    Serial.print(gps.time.minute());
    Serial.print(F(":"));
    if (gps.time.second() < 10) Serial.print(F("0"));
    Serial.print(gps.time.second());
    Serial.print(F("."));
    if (gps.time.centisecond() < 10) Serial.print(F("0"));
    Serial.print(gps.time.centisecond());
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.println();
}
This is what the serial monitor wrote. Actually it didn’t show any serial location data. This means that the code of line 29 and below was not running.

alt text

Please also note that I did it with my current laptop. Hoping I could get a better result, I tried this with my old laptop. The result was the same. Further, I rewrote the similar code with new RX and TX pins as shown in the following screenshots, only to find the disappointing message “GPS Start” followed by no more message.

alt text

alt text


Reflections

What was wrong with my exercises? I copied and pasted my last code on the ChatGPT and asked if there was anything with it. Here is the answer:

Your code looks mostly correct. However, there are a couple of potential issues that could be causing it not to work as expected:

  1. Wiring: Ensure that your GT-U7 GPS sensor is wired correctly to the Arduino UNO. The GT-U7 typically communicates via UART, so ensure that the RX pin of the GPS module is connected to pin 10 (TX of Arduino) and the TX pin of the GPS module is connected to pin 11 (RX of Arduino).

  2. Serial Communication: Double-check that the baud rates are set correctly. Both in your code (serial_connection.begin(9600)) and in the GT-U7 GPS sensor. Most GPS modules default to a baud rate of 9600, but it’s possible that yours might be configured differently.

  3. GPS Signal Reception: Make sure that your GPS module has a clear view of the sky to receive satellite signals. Indoors or in places with obstructed views might result in poor or no GPS signal reception.

  4. GPS Initialization: Some GPS modules may take some time to acquire satellite signals and provide valid location data, especially if it’s the first time it’s being used or if it’s been moved to a new location. Try leaving it powered on for a few minutes to see if it acquires a fix.

  5. Testing in an Open Area: If you’re testing indoors or in an area with poor GPS signal reception, try testing the setup in an open area with a clear view of the sky.

Try addressing these points, and if the issue persists, you may want to try debugging by adding additional Serial.println() statements to understand where the code might be failing. For example, you could print out the raw NMEA sentences received from the GPS module to ensure that data is being received correctly.

Uninstall and Reinstall Arduino IDE: In addtion to the points raised by ChatGPT, on Friday, April 19, I have started wondering if there is something wrong with the function of my laptop. I have already reported above the problem of uploading error with Arduino IDE. Our instructor advised that I should try uninstalling the Arduino IDE from my laptop and then delete all the Arduino-related folders in “My Document” and C-Drive. Then I reinstalled the Arduino IDE. Let’s see if it goes well. The results will be added later.

Try Raspberry Pi Pico W with MicroPython: Another possibility, which has emerged in the last few days, is that I should try Raspberry Pi Pico W for my final project, instead of Xiao ESP32C2. If this is the case, I should spend some time writing the similar codes with Thonny IDE for input devices connected to Pico W. This should also be explored and the results should be added later.


Wed. April 24, 2024

GPS Module with Arduino IDE for Arduino UNO/Xiao ESP32C3

As suggested by our Instructor, I once deleted all the Arduino-related folders in C-Drive and My Document, and uninstalled and reinstalled Arduino IDE. Imported the TinyGPS library once again and ran the following code with Arduino UNO and GT-U7.

#include <SoftwareSerial.h>

#include "TinyGPS.h"

/* This sample code demonstrates the normal use of a TinyGPS object.
   It requires the use of SoftwareSerial, and assumes that you have a
   4800-baud serial GPS device hooked up on pins 4(rx) and 3(tx).
*/

TinyGPS gps;
SoftwareSerial ss(4, 3);

static void smartdelay(unsigned long ms);
static void print_float(float val, float invalid, int len, int prec);
static void print_int(unsigned long val, unsigned long invalid, int len);
static void print_date(TinyGPS &gps);
static void print_str(const char *str, int len);

void setup()
{
  Serial.begin(115200);

  Serial.print("Testing TinyGPS library v. "); Serial.println(TinyGPS::library_version());
  Serial.println("by Mikal Hart");
  Serial.println();
  Serial.println("Sats HDOP Latitude  Longitude  Fix  Date       Time     Date Alt    Course Speed Card  Distance Course Card  Chars Sentences Checksum");
  Serial.println("          (deg)     (deg)      Age                      Age  (m)    --- from GPS ----  ---- to London  ----  RX    RX        Fail");
  Serial.println("-------------------------------------------------------------------------------------------------------------------------------------");

  ss.begin(4800);
}

void loop()
{
  delay(5000);
  float flat, flon;
  unsigned long age, date, time, chars = 0;
  unsigned short sentences = 0, failed = 0;
  static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;

  print_int(gps.satellites(), TinyGPS::GPS_INVALID_SATELLITES, 5);
  print_int(gps.hdop(), TinyGPS::GPS_INVALID_HDOP, 5);
  gps.f_get_position(&flat, &flon, &age);
  print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 10, 6);
  print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 11, 6);
  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
  print_date(gps);
  print_float(gps.f_altitude(), TinyGPS::GPS_INVALID_F_ALTITUDE, 7, 2);
  print_float(gps.f_course(), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
  print_float(gps.f_speed_kmph(), TinyGPS::GPS_INVALID_F_SPEED, 6, 2);
  print_str(gps.f_course() == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(gps.f_course()), 6);
  print_int(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0xFFFFFFFF : (unsigned long)TinyGPS::distance_between(flat, flon, LONDON_LAT, LONDON_LON) / 1000, 0xFFFFFFFF, 9);
  print_float(flat == TinyGPS::GPS_INVALID_F_ANGLE ? TinyGPS::GPS_INVALID_F_ANGLE : TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
  print_str(flat == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON)), 6);

  gps.stats(&chars, &sentences, &failed);
  print_int(chars, 0xFFFFFFFF, 6);
  print_int(sentences, 0xFFFFFFFF, 10);
  print_int(failed, 0xFFFFFFFF, 9);
  Serial.println();

  smartdelay(10000);
}

static void smartdelay(unsigned long ms)
{
  unsigned long start = millis();
  do 
  {
    while (ss.available())
      gps.encode(ss.read());
  } while (millis() - start < ms);
}

static void print_float(float val, float invalid, int len, int prec)
{
  if (val == invalid)
  {
    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 print_int(unsigned long val, unsigned long invalid, int len)
{
  char sz[32];
  if (val == invalid)
    strcpy(sz, "*******");
  else
    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 print_date(TinyGPS &gps)
{
  int year;
  byte month, day, hour, minute, second, hundredths;
  unsigned long age;
  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
  if (age == TinyGPS::GPS_INVALID_AGE)
    Serial.print("********** ******** ");
  else
  {
    char sz[32];
    sprintf(sz, "%02d/%02d/%02d %02d:%02d:%02d ",
        month, day, year, hour, minute, second);
    Serial.print(sz);
  }
  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
  smartdelay(0);
}

static void print_str(const char *str, int len)
{
  int slen = strlen(str);
  for (int i=0; i<len; ++i)
    Serial.print(i<slen ? str[i] : ' ');
  smartdelay(0);
}
Looked like it’s uploaded successfully. In order to get the better indication of the serial data on the monitor, I set the serial communication speed as 115200 and add “delay(5000);” after the “void loop()” line. Then it started showing the table but still it only shows “****”. I haven’t rectified this problem yet.

alt text

I further tested with Xiao ESP32C3 by the same code while I changed the RX/TX pin numbers. Then I faced “Compilation error: SoftwareSerial.h: No such file or directory”, which I didn’t face with Arduino UNO.

alt text

alt text

GPS Module with Thonny IDE for Raspberry Pi PicoW

Also, I found a YouTube video describing the MicroPython code for a GPS module with Raspberry Pi Pico. Although the GPS module was a different one, I tried it with GT-U7.

alt text

Here is the MicroPython code:

from machine import Pin, UART                                            
import utime, time

gpsx=UART(1, baudrate=9600, timeout=300, tx=Pin(4), rx=Pin(5))

while True:                                                                      
    try:                                                         
        if gpsx.any() > 0:                                  
            buff=str(gpsx.read())

            print(buff)
            print("------------------------------")

    except:
        pass

Fortunately I could get the serial data from the GPS module.

alt text

The above serial data contained a few different NMEA (National Marine Electronics Association) global positioning data, such as: GPRMC, GPVTG, GPGGA, GPGSA, GPGSV and GPGLL. The data sets for those NMEA formats are slightly different and we could be selective according to our requirements. In this case we need to add a few paragraphs on the above basic code. Maybe that should be my agenda in the future.


Sat. April 28, 2024

Time-of-Flight Distance Sensor with Arduino IDE for Xiao ESP32C3

I also would like to add that the Time-of-Flight Distance Sensor, VL53L0X, was also tested again with Xiao ESP32C3 and I could finally get the serial data. Although I only post the sample code “Single.ino” from the VL53L0X libraries, I would like to write that the other sample “Continuous.ino” was also tested and it worked.

/* This example shows how to get single-shot range
 measurements from the VL53L0X. The sensor can optionally be
 configured with different ranging profiles, as described in
 the VL53L0X API user manual, to get better performance for
 a certain application. This code is based on the four
 "SingleRanging" examples in the VL53L0X API.

 The range readings are in units of mm. */

#include <Wire.h>
#include "VL53L0X.h"

VL53L0X sensor;


// Uncomment this line to use long range mode. This
// increases the sensitivity of the sensor and extends its
// potential range, but increases the likelihood of getting
// an inaccurate reading because of reflections from objects
// other than the intended target. It works best in dark
// conditions.

//#define LONG_RANGE


// Uncomment ONE of these two lines to get
// - higher speed at the cost of lower accuracy OR
// - higher accuracy at the cost of lower speed

//#define HIGH_SPEED
//#define HIGH_ACCURACY


void setup()
{
  Serial.begin(9600);
  Wire.begin();

  sensor.setTimeout(500);
  if (!sensor.init())
  {
    Serial.println("Failed to detect and initialize sensor!");
    while (1) {}
  }

#if defined LONG_RANGE
  // lower the return signal rate limit (default is 0.25 MCPS)
  sensor.setSignalRateLimit(0.1);
  // increase laser pulse periods (defaults are 14 and 10 PCLKs)
  sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18);
  sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14);
#endif

#if defined HIGH_SPEED
  // reduce timing budget to 20 ms (default is about 33 ms)
  sensor.setMeasurementTimingBudget(20000);
#elif defined HIGH_ACCURACY
  // increase timing budget to 200 ms
  sensor.setMeasurementTimingBudget(200000);
#endif
}

void loop()
{
  Serial.print(sensor.readRangeSingleMillimeters());
  if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); }

  Serial.println();
}
alt text


Thu. June 20, 2024

GPS Module with Thonny IDE for Raspberry Pi PicoW II

It was pointed out that I had not completed my Individual Assignment for the Week, I did the extra work on testing my microcontroller board for the Final Project.

As I already described above, I have once tested the GT-U7 GPS module with Thonny IDE and PicoW two months ago. I did succeed in obtaining the serial GPS data that time. However, it contained a few different NMEA (National Marine Electronics Association) global positioning data, such as GPRMC, GPVTG, GPGGA, GPGSA, GPGSV and GPGLL. The data sets for those NMEA formats were slightly different from each other and I wrote that reading the global position data in the readable format should be my agenda in the future.

This was the only occasion I used the same board as the one I used for my Final Project. Therefore, I decided to work on this.

The code I used two months ago for PicoW had the following two problems:

  • Longitudinal and Latitudinal Data: Although it seemd that the longitudinal and latitudinal data were recorded in various NMEA formats, they were very complicating and it’s so difficult to pick up the longitude and latitude.

  • Date and Time: Most of the NMEA format didn’t include the date and time. We want to know when it was there in the location recorded.

According to the NMEA, GPRMC was the only the data format that includes the date and time. Therefore, I decided to choose the GPRMC data set and make the arrangement for the Thonny MicroPython shell to show the longitudinal and latitudinal data together with the date and time, customized to the Time Zone of Japan Starndard Time (9hrs. ahead of GMT).

UART Channel 0
TX Pin 12
RX Pin 13

alt text

First, I prepared the code to read all the data sets of NMEA format and see how the GPRMC data set looks like.

from machine import Pin, UART                                            
import utime, time

gpsx=UART(0, baudrate=9600, timeout=300, tx=Pin(12), rx=Pin(13))

while True:                                                                      
    try:                                                         
        if gpsx.any() > 0:                                  
            buff=str(gpsx.read())

            print(buff)
            print("------------------------------")

    except:
        pass

Then the Thonny shell indicated the following series of GPS data sets:

alt text

GPRMC format has more than 10 data, divided by comma. According to the NMEA website, the following serial numbers are the data I want.

SN Data
1 Time (GMT)
3 Latitude
5 Longitude
9 Date (Date/Month/Year)

Based on the above information, I prepared the following code. Original sample sketches were taken from 福田和宏著『最新Pico W対応!ラズパイPico完全ガイド』. Based on the two sample sketches for longitudinal and latitudinal data and for date and time, I combined the two so that I could take all the four data from GPRMC.

from machine import Pin, UART
import time

ALERT_COUNT = 100

TIMEZONE = +9

UART_CH = 0
UART_TX = 12
UART_RX = 13

uart = UART( UART_CH, baudrate=9600, tx=Pin( UART_TX ), rx=Pin( UART_RX ) )

alert_cnt = 0

def dm_to_deg( data ):
    deg = int ( float(data) / 100 )
    min = float( data ) - deg * 100
    return( round( deg + min / 60.0 , 6 ) )

while(True):
    buf = bytes()
    gps_line = ''
    result = False
    while ( True ):
        if( uart.any() > 0 ):
            buf = uart.read( 1 )
            if ( buf == b'\r' ):
                break
            elif( buf[0] > 0x20 and buf[0] < 0x7f ):
                gps_line += buf.decode( )
                time.sleep(0.0001)

    if( gps_line != '' ):
        gps_data = gps_line.split(",")
        if ( gps_data[0] == '$GPRMC' ):
            gnss_date = gps_data[9]
            gnss_time = gps_data[1]
            lat = gps_data[3]
            long = gps_data[5]

        if ( len( gps_data ) > 2 ):
            if ( gps_data[2] == "A" ):
                result = True

        if ( result == True ):
            y = int( '20' + gnss_date[4:6] )
            m = int( gnss_date[2:4] )
            d = int( gnss_date[0:2] )
            h = int( gnss_time[0:2] )
            min = int( gnss_time[2:4] )
            sec = int( gnss_time[4:6] )
            lat_deg = dm_to_deg( lat )
            long_deg = dm_to_deg( long )

            utime = time.mktime([y,m,d,h,min,sec,0,0])

            tz = TIMEZONE * 60 * 60
            ltime = utime + tz

            (year,month,day,hour,minut,second,week,buf) = time.localtime( ltime )

            print("{}/{}/{} {}:{}:{}".format(year,month,day,hour,minut,second) )
            print("Latitude:{:} Longitude:{:}".format( lat_deg, long_deg ) )
            alert_cnt = 0

        else:
            alert_cnt = alert_cnt + 1
            if( alert_cnt > ALERT_COUNT ):
                print("Not get data.")
                alert_cnt = 0

A few seconds after I uploaded the program to the PicoW board, it started reading the GPS data and the Thonny shell started recording the longitudinal and latitudinal data every second together with the date and time it received the data.

alt text

To make sure that the longitude and latitude surely indicate my location, I copied and pasted the two data in the Search window on the Google Map, and confirmed that the location data was almost correct.

alt text


Last update: June 22, 2024