I2C intefering with serial.read()

Discussions about the STM32generic core
Post Reply
User avatar
Manny
Posts: 74
Joined: Wed Dec 09, 2015 3:15 pm

I2C intefering with serial.read()

Post by Manny » Wed Jan 31, 2018 4:07 pm

I have run into a problem with the Wire lib and using serial.read() together.

My Setup:
STM32F407VET6 mini
DS3231 and VL53L0X on I2C1
GPS module on Serial2 (PA2, PA3)

I'm reading the GPS U-Blox binary data no problem on its own, but as soon as I try and read any of the I2C devices it fails. I did have all my code working nicely together using libmaple and stm32F103 as a gps logger ...any ideas?

Fusion table example HERE

GPS NAV-PVT read class

Code: Select all

void GPS_UBLOXPVT_Class::Read(void)
{
	static unsigned long GPS_timer = 0;
	byte data;
	int numc;

	numc= Serial2.available();

	if (numc > 0)
		for (int i = 0; i < numc; i++)	// Process bytes received
			{
		     	data = Serial2.read();

		    //Serial.println(data);
			switch(UBX_step)		 // Normally we start from zero. This is a state machine
			{
			case 0:
				if(data == 0xB5){	// UBX sync char 1
					UBX_step++;	 // OH first data packet is correct, so jump to the next step
				}
				break;

			case 1:
				if(data == 0x62){	// UBX sync char 2
					UBX_step++;	 // ooh! The second data packet is correct, jump to the step 2
				}
				else
					UBX_step = 0;	 // Nop, is not correct so restart to step zero and try again.
				break;

			case 2:
				UBX_class = data;
				ubx_checksum(UBX_class);
				UBX_step++;
				break;

			case 3:
				UBX_id = data;
				ubx_checksum(UBX_id);
				UBX_step++;
				break;

			case 4:
				UBX_payload_length_hi = data;
				ubx_checksum(UBX_payload_length_hi);
				UBX_step++;

		// We check if the payload lenght is valid...
			if (UBX_payload_length_hi >= UBX_MAXPAYLOAD)
				{
				UBX_step = 0;	 // Bad data, so restart to step zero and try again.
				ck_a = 0;
				ck_b = 0;
				}
				break;
			case 5:
				UBX_payload_length_lo = data;
				ubx_checksum(UBX_payload_length_lo);
				UBX_step++;
		UBX_payload_counter = 0;
				break;

			case 6:				 // Payload data read...
				if (UBX_payload_counter < UBX_payload_length_hi)	// We stay in this state until we reach the payload_length
				{
					UBX_buffer[UBX_payload_counter] = data;
					ubx_checksum(data);
					UBX_payload_counter++;
					if (UBX_payload_counter == UBX_payload_length_hi)
					UBX_step++;
				}
				break;

			case 7:
				UBX_ck_a = data;	 // First checksum byte
				UBX_step++;
				break;

			case 8:
				UBX_ck_b = data;	 // Second checksum byte

	  // We end the GPS read...
				if((ck_a == UBX_ck_a) && (ck_b == UBX_ck_b))	 // Verify the received checksum with the generated checksum..
				parse_ubx_gps();							 // Parse the new GPS packet
				else
			{
			//Errors, something could be done
			//Serial.print("ERROR READING");
			}
        // Variable initialization
				UBX_step = 0;
				ck_a = 0;
				ck_b = 0;
				GPS_timer = millis(); // Restarting timer...
				break;
		}
		}		// End for 2 seconds If we don´t receive GPS packets in 2 seconds => Bad FIX state
	if ((millis() - GPS_timer) > 2000)
		{
	Fix = 0;
	//Serial.println("Bad Fix");  //debug
		}
}

User avatar
mrburnette
Posts: 2220
Joined: Mon Apr 27, 2015 12:50 pm
Location: Greater Atlanta
Contact:

Re: I2C intefering with serial.read()

Post by mrburnette » Wed Jan 31, 2018 5:05 pm

Manny wrote:
Wed Jan 31, 2018 4:07 pm
I have run into a problem with the Wire lib and using serial.read() together.

My Setup:
STM32F407VET6 mini
DS3231 and VL53L0X on I2C1
GPS module on Serial2 (PA2, PA3)

I'm reading the GPS U-Blox binary data no problem on its own, but as soon as I try and read any of the I2C devices it fails. I did have all my code working nicely together using libmaple and stm32F103 as a gps logger ...any ideas?
I'm not a big fan of building a class that has this construct:

Code: Select all

if (numc > 0)
I assume that loop() is where your I2C stuff gets processed?

Would it not be better to have the

Code: Select all

if (numc > 0)
in the loop() and only operate on parsing if you have both clean-data and a CR/NL in the buffer? I rather like the manner in which Lady Ada created her GPS lib:
https://github.com/adafruit/Adafruit_GPS

Code: Select all

// Test code for Ultimate GPS Using Hardware Serial (e.g. GPS Flora or FeatherWing)
//
// This code shows how to listen to the GPS module via polling. Best used with
// Feathers or Flora where you have hardware Serial and no interrupt
//
// Tested and works great with the Adafruit GPS FeatherWing
// ------> https://www.adafruit.com/products/3133
// or Flora GPS
// ------> https://www.adafruit.com/products/1059
// but also works with the shield, breakout
// ------> https://www.adafruit.com/products/1272
// ------> https://www.adafruit.com/products/746
// 
// Pick one up today at the Adafruit electronics shop
// and help support open source hardware & software! -ada
     
#include <Adafruit_GPS.h>

// what's the name of the hardware serial port?
#define GPSSerial Serial1

// Connect to the GPS on the hardware port
Adafruit_GPS GPS(&GPSSerial);
     
// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
// Set to 'true' if you want to debug and listen to the raw GPS sentences
#define GPSECHO false

uint32_t timer = millis();


void setup()
{
  //while (!Serial);  // uncomment to have the sketch wait until Serial is ready
  
  // connect at 115200 so we can read the GPS fast enough and echo without dropping chars
  // also spit it out
  Serial.begin(115200);
  Serial.println("Adafruit GPS library basic test!");
     
  // 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800
  GPS.begin(9600);
  // uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  // uncomment this line to turn on only the "minimum recommended" data
  //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
  // For parsing data, we don't suggest using anything but either RMC only or RMC+GGA since
  // the parser doesn't care about other sentences at this time
  // Set the update rate
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate
  // For the parsing code to work nicely and have time to sort thru the data, and
  // print it out we don't suggest using anything higher than 1 Hz
     
  // Request updates on antenna status, comment out to keep quiet
  GPS.sendCommand(PGCMD_ANTENNA);

  delay(1000);
  
  // Ask for firmware version
  GPSSerial.println(PMTK_Q_RELEASE);
}

void loop() // run over and over again
{
  // read data from the GPS in the 'main loop'
  char c = GPS.read();
  // if you want to debug, this is a good time to do it!
  if (GPSECHO)
    if (c) Serial.print(c);
  // if a sentence is received, we can check the checksum, parse it...
  if (GPS.newNMEAreceived()) {
    // a tricky thing here is if we print the NMEA sentence, or data
    // we end up not listening and catching other sentences!
    // so be very wary if using OUTPUT_ALLDATA and trytng to print out data
    Serial.println(GPS.lastNMEA()); // this also sets the newNMEAreceived() flag to false
    if (!GPS.parse(GPS.lastNMEA())) // this also sets the newNMEAreceived() flag to false
      return; // we can fail to parse a sentence in which case we should just wait for another
  }
  // if millis() or timer wraps around, we'll just reset it
  if (timer > millis()) timer = millis();
     
  // approximately every 2 seconds or so, print out the current stats
  if (millis() - timer > 2000) {
    timer = millis(); // reset the timer
    Serial.print("\nTime: ");
    Serial.print(GPS.hour, DEC); Serial.print(':');
    Serial.print(GPS.minute, DEC); Serial.print(':');
    Serial.print(GPS.seconds, DEC); Serial.print('.');
    Serial.println(GPS.milliseconds);
    Serial.print("Date: ");
    Serial.print(GPS.day, DEC); Serial.print('/');
    Serial.print(GPS.month, DEC); Serial.print("/20");
    Serial.println(GPS.year, DEC);
    Serial.print("Fix: "); Serial.print((int)GPS.fix);
    Serial.print(" quality: "); Serial.println((int)GPS.fixquality);
    if (GPS.fix) {
      Serial.print("Location: ");
      Serial.print(GPS.latitude, 4); Serial.print(GPS.lat);
      Serial.print(", ");
      Serial.print(GPS.longitude, 4); Serial.println(GPS.lon);
      Serial.print("Speed (knots): "); Serial.println(GPS.speed);
      Serial.print("Angle: "); Serial.println(GPS.angle);
      Serial.print("Altitude: "); Serial.println(GPS.altitude);
      Serial.print("Satellites: "); Serial.println((int)GPS.satellites);
    }
  }
}
Ray

User avatar
Manny
Posts: 74
Joined: Wed Dec 09, 2015 3:15 pm

Re: I2C intefering with serial.read()

Post by Manny » Wed Jan 31, 2018 6:30 pm

mrburnette wrote:
Wed Jan 31, 2018 5:05 pm

I'm not a big fan of building a class that has this construct:

Code: Select all

if (numc > 0)
There is a little more to the code which is not mine by the way (I'm a plumber :D ), checks headers, does checksum and reads very reliably at 10hz without all that relatively costly NMEA parsing.
mrburnette wrote:
Wed Jan 31, 2018 5:05 pm
I assume that loop() is where your I2C stuff gets processed?
Yes, the gps code in loop is quite simple

Code: Select all

  
  void loop() {
  
  GPS.Read();
  
  if (GPS.NewData) { //Move on if there are any new GPS data 
    GPS.NewData = 0; // Message to GPS library that new data is received
   //log stuff to SD SDIO
   } 
  } 
 
But as soon as you start reading I2c it breaks.

Code: Select all

  
  void loop() {
  
  tc = rtc.now();
  
  GPS.Read();
  
  if (GPS.NewData) { //Move on if there are any new GPS data 
    GPS.NewData = 0; // Message to GPS library that new data is received
   //log stuff to SD SDIO
   }
  }  
 
More than likely something I have overlooked but its bugging me now.

User avatar
Manny
Posts: 74
Joined: Wed Dec 09, 2015 3:15 pm

Re: I2C intefering with serial.read()

Post by Manny » Thu Feb 01, 2018 6:34 pm

The problem is I2C running so slow that serial read is skipping bytes :o Further test needed.

Edit.. Is there a I2C bit bang version available with STM32Generic?

FiveO
Posts: 27
Joined: Mon Oct 16, 2017 6:41 am

Re: I2C intefering with serial.read()

Post by FiveO » Thu Feb 01, 2018 6:43 pm

Manny wrote:
Thu Feb 01, 2018 6:34 pm
The problem is I2C running so slow that serial read is skipping bytes :o Further test needed.
I had similar problems with driving nema motors and I2C read and serial print, after changing I2C to 400khz, problem solved. Tested up to 800khz, 900khz it faild.

User avatar
Manny
Posts: 74
Joined: Wed Dec 09, 2015 3:15 pm

Re: I2C intefering with serial.read()

Post by Manny » Thu Feb 01, 2018 6:56 pm

FiveO wrote:
Thu Feb 01, 2018 6:43 pm
I had similar problems with driving nema motors and I2C read and serial print, after changing I2C to 400khz, problem solved. Tested up to 800khz, 900khz it faild.
I'll give that a go, already tried 4000khz and didn't see any speed difference, the only thing I can use to diagnose with, is putting a timer on the main loop. I have used the same setup on a Bluepill with the pre-hardware bitbang I2C and it was running pretty good.

User avatar
mrburnette
Posts: 2220
Joined: Mon Apr 27, 2015 12:50 pm
Location: Greater Atlanta
Contact:

Re: I2C intefering with serial.read()

Post by mrburnette » Thu Feb 01, 2018 10:46 pm

I used GPS serial, I2C, and SPI here https://www.hackster.io/rayburne/color- ... ock-a8b121 and did not have issues, but there have been core changes since that time.

Code: Select all

#include <SPI.h>                                     // \Documents\Arduino\hardware\STM32\STM32F1\libraries\SPI
#include <Wire.h>                                    // I2C \Documents\Arduino\hardware\STM32\STM32F1\libraries\Wire (legacy)
#include <Streaming.h>                               // \Documents\Arduino\libraries\Streaming (legacy)

#include ".\BMP085.h"                                // #include "I2Cdev.h" is pulled in also
#include ".\Adafruit_GPS.h"
#include ".\Adafruit_GFX.h"
#include ".\Adafruit_ILI9341.h"
#include ".\SoftwareSerial.h"                        // faux version only for STM32 Maple
#include ".\Utilities.h"
Ray

Post Reply