FEZ Cerberus Serial and I2C Mutually Exclusive?

I’ve got a Gadgeteer project set up as follows:

Socket 1: Seeed Compass (I2C)
Socket 2: Seeed GPS (UART 2)
Socket 6: Custom RS485 board (UART 3)

I get the serial port (Socket 6/COM3) like this:

_socket = Socket.GetSocket(6, true, null, null);
var serialPortName = _socket.SerialPortName;
_serial = new SerialPort(serialPortName, 19200, Parity.None, 8, StopBits.One);

Compass and GPS are initialized like so:

compass.MeasurementComplete += CompassMeasurementComplete;
compass.StartContinuousMeasurements();  // should see an event every 200ms
gps.PositionReceived += GpsPositionReceived;  // starts GPS automagically

I also have a Timer callback that is used for some collation tasks (nothing blocking) and starts after about 5s. Until then i get Compass readings fine.
When I open the serial port

if (!_serial.IsOpen) _serial.Open();

the Compass stops working. So I assume that the I2C has stopped. I’ve had a look at the Seeed driver and I can’t find anything there that would cause the issue.

I have successfully run with just the GPS and Compass, but if I put the GPS in Socket 6 I get no Compass readings at all.


I’ve worked out that this is definitely related to opening COM3. If the GPS is in Socket 6, as soon as you set gps.Enabled = true the compass stops wokring - I2C appears to be stalled. This corresponds to the GPS opening the serial port.

I’ll try to verify this with a scope tonight and report back.

I do not have a Cerberus schematic available, but uart numbering usually begins with uart0, so uart3 would be com4

Not on the Cerberus MPU. STM has it set, at least for this chip that is on Cerberus, that the UART starts at 1 and not 0.

Oh well, it was a good guess that was wrong. :slight_smile:

@ Mike, that’s also what the var serialPortName = _socket.SerialPortName; is for :slight_smile:

I’ve tested this with 3 Cerberus now, so I’m pretty sure it’s not a one off hardware issue.

Next step is to see if I can get the compass working again after I open and close UART3. I’m using the latest 4.2 release, btw.

Can I suggest another test - swap the device on COM3 and see if the behaviour changes. Might be some really weird issue just related to that device; if when you enable com3 you still get I2C stopping, then it’s a much easier repro as well for GHI to look into.

@ Brett, I’ll do that test again, I think I did it yesterday but I’m not completely sure. I seem to recall that even without the GPS in the project, opening COM3 stopped the I2C.

I more meant can you swap your socket 2 and 6 devices so you know that the code in the GPS module isn’t playing funny with it - but a real simple repro test app that only does I2C and just opens com3 in a vanilla way should also suffice (in fact it’d be ideal for testing)

@ Brett, definitely did the first test, and I get no compass data at all. Presumably because the GPS opens the UART as the driver starts.

OK, getting closer.
What is happening at the moment is when/after the UART is opened the dataReady.Interrupt event stops firing. I really need to get the scope onto it to make sure that the pin is toggling. I’ve added some Debug.Prints to the Compass driver to find this.
It looks like the I2C.Write is working (it’s returning the correct numebr of bytes written, although I’m not sure the CLR really cares what state the peripheral is in (I could be wrong :slight_smile: )
Will let you know if it’s hardware or software.

I’m almost certain it’s not a hardware issue now.
This is the debug output:

Compass : Measurement Timer
Compass : RequestMeasurement returned 2
Compass : DataReady_Interrupt
PulseDebugLED called
Compass : Measurement Timer
Compass : RequestMeasurement returned 2
Compass : DataReady_Interrupt
PulseDebugLED called
Compass : Measurement Timer
Compass : RequestMeasurement returned 2
Compass : DataReady_Interrupt
PulseDebugLED called
$TELMY,STA132,UTC1601-01-01 00:00:00Z,HDG346.75948524171076,LAT0,LON0
Compass : Measurement Timer
Compass : RequestMeasurement returned 2
Compass : Measurement Timer
Compass : RequestMeasurement returned 2

“Compass : Measurement Timer” is the trigger timer that starts a request chain.
“Compass : RequestMeasurement returned 2” returned 2 bytes written to I2C
"Compass : DataReady_Interrupt" Compass driver interrupt triggered when compass module has new data (then reads new values from I2C buffer)
“PulseDebugLED called” is in my “CompassMeasurementComplete” event handler
The string is what’s written to the, completely independent, UART. (Serial.Open(), Transmit, wait for buffer empty, Close).
You can see that immediately following the UART Open() no more “Compass : DataReady_Interrupt” events are fired.

I even tried manually triggering the pin by applying 3.3V and ground to the socket Pin3.
The GTI.InterruptInput.Interrupt event is not null at this point.

More new information:
If I open the serial port before creating the Compass module (in ProgramStarted) the system works correctly - I can send through the UART and the Compass I2C works.
Anyone at GHI got any ideas? Could it be a porting issue? I’ll dig into the porting code when I’ve got time, but I’d prefer easy answers :slight_smile:

If you are seeing a problem with stock firmware then please provide steps for us to repro.

@ Gus, repro steps:

new Gadgeteer project
Socket1: Seeed Compass module, stock driver
Socket2: Seeed GPS Module, stock driver
Socket6: FTDI 3.3V TTL Serial cable - only Cerberus TX connected

private SerialPort _serial;
private Timer _mainTimer;
private void ProgramStarted()
  compass.MeasurementComplete += CompassMeasurementComplete;
  gps.PositionReceived += GpsPositionReceived;  // optional
  _serial = new SerialPort(Socket.GetSocket(6, true, null, null).SerialPortName, 19200, Parity.None, 8, StopBits.One);
  _mainTimer =  new Timer(MainTimerCallback, null, 5000, 1000);

private void CompassMeasurementComplete(Compass sender, Compass.SensorData sensorData)
private void MainTimerCallback(object stateInfo) 
  if(!_serial.IsOpen) _serial.Open();  // here it fails
  ... send serial data

Expected: Debug led keeps flashing (Compass event keeps getting called)
See: After 5s (Main timer start) Compass event no longer fires.

Verification: If you open the serial port in ProgramStarted you get no Compass events at all. If you open the serial port in ProgramStarted before you create a new compass on Socket 1 you can use the serial port and the compass.

@ Byron -

Make sure that the _mainTimer object created is a GT.Timer object not a MF timer.

I don’t have a development system available, so I can’t check it out.

@ Mike,

Any particular reason? The error can be produced by opening the serial port in the ProgramStarted method, then there will be no Compass updates at all.

Gadgeteer has its own dispatching mechanism for events. Doing mixed event handling can/does cause problems.

I’m giving up on this for now - need to move on.

I’m going to open the serial port before I call the Compass ctor and see if it stays open.

Here’s crossed fingers :slight_smile: