Gyro causing exceptions on Hydra+

I am getting exceptions from the Gyro module running on a Hydra+.

With this code;

using System;
using System.Collections;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Presentation;
using Microsoft.SPOT.Presentation.Controls;
using Microsoft.SPOT.Presentation.Media;
using Microsoft.SPOT.Presentation.Shapes;
using Microsoft.SPOT.Touch;
using Microsoft.SPOT.Hardware;

using Gadgeteer.Networking;
using GT = Gadgeteer;
using GTM = Gadgeteer.Modules;
using Gadgeteer.Modules.GHIElectronics;

namespace HydraTest2
{
    public partial class Program
    {
        // This method is run when the mainboard is powered up or reset.   
        void ProgramStarted()
        {
            /*******************************************************************************************
            Modules added in the Program.gadgeteer designer view are used by typing 
            their name followed by a period, e.g.  button.  or  camera.
            
            Many modules generate useful events. Type +=<tab><tab> to add a handler to an event, e.g.:
                button.ButtonPressed +=<tab><tab>
            
            If you want to do something periodically, use a GT.Timer and handle its Tick event, e.g.:
                GT.Timer timer = new GT.Timer(1000); // every second (1000ms)
                timer.Tick +=<tab><tab>
                timer.Start();
            *******************************************************************************************/
            
            // Use Debug.Print to show messages in Visual Studio's "Output" window during debugging.
            Debug.Print("Program Started");

            gyro.Calibrate();
            gyro.MeasurementComplete += gyro_MeasurementComplete;
            gyro.StartTakingMeasurements();
        }

        void gyro_MeasurementComplete(Gyro sender, Gyro.MeasurementCompleteEventArgs e)
        {
            Debug.Print("X= " + e.X.ToString("F0"));
            Debug.Print("Y= " + e.Y.ToString("F0"));
            Debug.Print("Z= " + e.Z.ToString("F0"));
            Debug.Print("Temp= " + e.Temperature.ToString("F0"));
        }

    }
}

I get the following output;

Program Started
X= 0
Y= 0
Z= -0
Temp= 20
X= 0
Y= 0
Z= 0
Temp= 20
X= -0
Y= 0
Z= -0
Temp= 21
X= 0
Y= 0
Z= 0
Temp= 21
X= 0
Y= 0
Z= 0
Temp= 20
X= 0
Y= -0
Z= 0
Temp= 20
X= 0
Y= 0
Z= 0
Temp= 21
X= 0
Y= 0
Z= 0
Temp= 20
X= 0
Y= -0
Z= 0
Temp= 20
X= 1
Y= -0
Z= -0
Temp= 20
X= 0
Y= 0
Z= 0
Temp= 20
X= 0
Y= 0
Z= -0
Temp= 20
X= 0
Y= 0
Z= 0
Temp= 20
X= 0
Y= 0
Z= -0
Temp= 20
X= -0
Y= 0
Z= -0
Temp= 20
X= 1
Y= 0
Z= 0
Temp= 20
X= 0
Y= 0
Z= -0
Temp= 20
X= 1
Y= 0
Z= 0
Temp= 20
X= 0
Y= 0
Z= 0
Temp= 20
X= 0
Y= 0
Z= 0
Temp= 20
X= 0
Y= 0
Z= 0
Temp= 20
X= 0
Y= 0
Z= 0
Temp= 20
X= 0
Y= 0
Z= 0
Temp= 20
X= 0
Y= 0
Z= 0
Temp= 20
X= 0
Y= 0
Z= 0
Temp= 20
X= 0
Y= 0
Z= -0
Temp= 20
X= 0
Y= 0
Z= -0
Temp= 21
X= -0
Y= 0
Z= 0
Temp= 20
X= -2
Y= 0
Z= 0
Temp= 20
X= -1
Y= 0
Z= 0
Temp= 20
X= 0
Y= 0
Z= 0
Temp= 20
X= 0
Y= 0
Z= 0
Temp= 20
X= 0
Y= 0
Z= -0
Temp= 20
X= 0
Y= 0
Z= -0
Temp= 20
X= 0
Y= 0
Z= 0
Temp= 20
X= 0
Y= 0
Z= 0
Temp= 21
X= 0
Y= 0
Z= 0
Temp= 20
X= 0
Y= 0
Z= 0
Temp= 20
X= 0
Y= 0
Z= 0
Temp= 20
X= 0
Y= 0
Z= 0
Temp= 20
X= 0
Y= 0
Z= -0
Temp= 20
X= 0
Y= 0
Z= -0
Temp= 20
X= 0
Y= -0
Z= -0
Temp= 20
X= 0
Y= 0
Z= -0
Temp= 20
X= 0
Y= 0
Z= 0
Temp= 20
X= 0
Y= 0
Z= -0
Temp= 21
X= 0
Y= 0
Z= -0
Temp= 20
The thread '<No Name>' (0x3) has exited with code 0 (0x0).
X= 0
Y= 0
Z= 0
Temp= 20
X= 0
Y= 0
Z= 0
Temp= 20
X= 0
Y= 0
Z= 0
Temp= 21
X= -14
Y= 2
Z= -1
Temp= 20
X= -3
Y= -1
Z= 0
Temp= 21
X= 0
Y= 0
Z= -0
Temp= 20
X= 0
Y= 0
Z= 0
Temp= 21
X= 0
Y= 0
Z= -0
Temp= 20
X= 0
Y= 0
Z= 0
Temp= 20
X= 15
Y= -5
Z= -52
Temp= 21
X= 27
Y= -4
Z= -3
Temp= 21
X= 30
Y= -20
Z= -56
Temp= 20
X= 46
Y= -9
Z= -60
Temp= 20
X= 11
Y= -26
Z= -7
Temp= 20
X= -31
Y= 0
Z= 109
Temp= 21
X= -17
Y= -30
Z= -88
Temp= 20
X= -163
Y= -3
Z= 68
Temp= 21
X= -108
Y= -15
Z= 47
Temp= 21
X= -36
Y= -5
Z= 16
Temp= 21
X= 24
Y= -13
Z= -38
Temp= 21
X= 64
Y= 35
Z= 31
Temp= 21
X= 94
Y= -2
Z= -117
Temp= 21
    #### Exception System.ApplicationException - 0x00000000 (4) ####
    #### Message: SoftwareI2C: Exception writing to device at address 104 - perhaps device is not responding or not plugged in.
    #### Gadgeteer.SocketInterfaces.NativeI2CBus::Execute [IP: 004e] ####
    #### Gadgeteer.SocketInterfaces.NativeI2CBus::WriteRead [IP: 0073] ####
    #### Gadgeteer.SocketInterfaces.I2CBus::WriteRead [IP: 0022] ####
    #### Gadgeteer.Modules.GHIElectronics.Gyro::Read [IP: 0016] ####
    #### Gadgeteer.Modules.GHIElectronics.Gyro::OnInterrupt [IP: 0006] ####
    #### Gadgeteer.SocketInterfaces.NativeInterruptInput::OnPortInterrupt [IP: 0008] ####
A first chance exception of type 'System.ApplicationException' occurred in Gadgeteer.dll
An unhandled exception of type 'System.ApplicationException' occurred in Gadgeteer.dll
Additional information: SoftwareI2C: Exception writing to device at address 104 - perhaps device is not responding or not plugged in.
The program '[2] Micro Framework application: Managed' has exited with code 0 (0x0).

It seems to be related to when I start moving the gyro around, however if I send the output to an N18 I get a load of random results and then an exception without moving the gyro at all. This leads me to think that it’s an issue with the Hydra’s digital I/O maybe?

Any help is much appreciated.

@ wolfbuddy - The Hydra is pretty noisy. Do you have a second gyro or other mainboard you can try?

Tested the gyro module just now on a Cerb Bee and it appears to be OK. Debug output is correct and it doesn’t crash when I move the module around.

However, when displaying the results on an N18 I get a load of random numbers from each axis. Is that because the output of the gyro is too fast for the display?

I also get this in the output;

Using mainboard GHI Electronics FEZ Cerbuino Bee version 1.2
Failed allocation for 3419 blocks, 41028 bytes

The thread '<No Name>' (0x3) has exited with code 0 (0x0).
Failed allocation for 66 blocks, 792 bytes

The program '[5] Micro Framework application: Managed' has exited with code 0 (0x0).

I know the Bee is short on memory but I though it could drive one of these displays?

Can you confirm if the output of the gyro axis’ are in rads/s or deg/s?

Cheers

it can but it can’t. Memory is a real constraint. If you want to try a slimmed down approach, https://www.ghielectronics.com/community/forum/topic?id=14026&page=1 is a thread where @ taylorza made some super suggestions.

OK thanks, I’ll look into that. To be honest I knew that the memory size of the Bee could be a limitation.

My main concern is John’s comment about the I2C bus crashing caused by the Hydra+ being ‘noisy’ and the random numbers that the gyro is producing on both main boards when displaying on the N18.

@ wolfbuddy - I can’t say what would be causing the random numbers on the display without seeing the code for it.

As for the Hydra, can you try different sockets? Do you have anything else connected besides the N18, even if it’s not being used? Can you try it without the N18 connected? Which SDK version are you on?

Looks like it’s socket #5 on the Hydra that is the main problem. Using socket #6 it doesn’t crash when just outputting to the debug window.

However, with the N18 connected and displaying gyro results with the code shown below I get random X, Y and Z numbers and a temperature value of 84 degC.


using System;
using System.Collections;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Presentation;
using Microsoft.SPOT.Presentation.Controls;
using Microsoft.SPOT.Presentation.Media;
using Microsoft.SPOT.Presentation.Shapes;
using Microsoft.SPOT.Touch;
using Microsoft.SPOT.Hardware;

using Gadgeteer.Networking;
using GT = Gadgeteer;
using GTM = Gadgeteer.Modules;
using Gadgeteer.Modules.GHIElectronics;

namespace HydraTest2
{
    public partial class Program
    {
        // This method is run when the mainboard is powered up or reset.   
        void ProgramStarted()
        {
            /*******************************************************************************************
            Modules added in the Program.gadgeteer designer view are used by typing 
            their name followed by a period, e.g.  button.  or  camera.
            
            Many modules generate useful events. Type +=<tab><tab> to add a handler to an event, e.g.:
                button.ButtonPressed +=<tab><tab>
            
            If you want to do something periodically, use a GT.Timer and handle its Tick event, e.g.:
                GT.Timer timer = new GT.Timer(1000); // every second (1000ms)
                timer.Tick +=<tab><tab>
                timer.Start();
            *******************************************************************************************/
            
            // Use Debug.Print to show messages in Visual Studio's "Output" window during debugging.
            Debug.Print("Program Started");

            this.displayN18.SimpleGraphics.DisplayRectangle(GT.Color.White, 1, GT.Color.White, 0, 0, this.displayN18.Width, this.displayN18.Height);

            gyro.Calibrate();
            gyro.MeasurementComplete += gyro_MeasurementComplete;
            gyro.StartTakingMeasurements();
         }

        void gyro_MeasurementComplete(Gyro sender, Gyro.MeasurementCompleteEventArgs e)
        {
            this.displayN18.SimpleGraphics.DisplayRectangle(GT.Color.White, 1, GT.Color.White, 20, 12, this.displayN18.Width, 12);
            this.displayN18.SimpleGraphics.DisplayRectangle(GT.Color.White, 1, GT.Color.White, 20, 26, this.displayN18.Width, 12);
            this.displayN18.SimpleGraphics.DisplayRectangle(GT.Color.White, 1, GT.Color.White, 20, 40, this.displayN18.Width, 12);
            this.displayN18.SimpleGraphics.DisplayRectangle(GT.Color.White, 1, GT.Color.White, 47, 54, this.displayN18.Width, 12);

            this.displayN18.SimpleGraphics.DisplayText("X= " + e.X.ToString("F0"), Resources.GetFont(Resources.FontResources.NinaB), GT.Color.Black, 2, 12);
            this.displayN18.SimpleGraphics.DisplayText("Y= " + e.Y.ToString("F0"), Resources.GetFont(Resources.FontResources.NinaB), GT.Color.Black, 2, 26);
            this.displayN18.SimpleGraphics.DisplayText("Z= " + e.Z.ToString("F0"), Resources.GetFont(Resources.FontResources.NinaB), GT.Color.Black, 2, 40);
            this.displayN18.SimpleGraphics.DisplayText("Temp= " + e.Temperature.ToString("F0"), Resources.GetFont(Resources.FontResources.NinaB), GT.Color.Black, 2, 54);

       }

    }
}


Then it eventually will crash with an I2C exception;


 #### Exception System.ApplicationException - 0x00000000 (4) ####
    #### Message: SoftwareI2C: Exception writing to device at address 104 - perhaps device is not responding or not plugged in.
    #### Gadgeteer.SocketInterfaces.NativeI2CBus::Execute [IP: 004e] ####
    #### Gadgeteer.SocketInterfaces.NativeI2CBus::WriteRead [IP: 0073] ####
    #### Gadgeteer.SocketInterfaces.I2CBus::WriteRead [IP: 0022] ####
    #### Gadgeteer.Modules.GHIElectronics.Gyro::Read [IP: 0016] ####
    #### Gadgeteer.Modules.GHIElectronics.Gyro::OnInterrupt [IP: 0006] ####
    #### Gadgeteer.SocketInterfaces.NativeInterruptInput::OnPortInterrupt [IP: 0008] ####
A first chance exception of type 'System.ApplicationException' occurred in Gadgeteer.dll
An unhandled exception of type 'System.ApplicationException' occurred in Gadgeteer.dll
Additional information: SoftwareI2C: Exception writing to device at address 104 - perhaps device is not responding or not plugged in.

This is all with the 2014 R4 package. I’ve rolled back from R5 because the N18 doesn’t work correctly with the Hydra in that package.

@ wolfbuddy - Seeing that it works well on the Cerb Bee, what happens if you run the gyro with just a vanilla code on the Hydra+ without having the display hooked up? This will eliminate the display should the exception re-occurs.

Yeah, it always crashes when the gyro is in socket #5 even without the screen.

@ wolfbuddy - The failures on socket 6 are likely due to noise. I reworked your code for the display, see below, and it no longer displays the incorrect data. The DisplayN18 is not meant for high speed refreshing. It communicates over a slow SPI bus. Displaying data from a gyroscope or similar sensor that changes its output rapidly is not really a good idea. You’ll notice the only refreshes once every two seconds and in a separate thread than the gyro event. Since display drawing is so slow, you do not want to block the event system with it.


using Gadgeteer.Modules.GHIElectronics;
using Microsoft.SPOT;
using GT = Gadgeteer;

namespace GadgeteerApp1 {
	public partial class Program {
		private GT.Timer timer;
		private double x;
		private double y;
		private double z;
		private double temp;

		void ProgramStarted() {
			this.displayN18.SimpleGraphics.DisplayRectangle(GT.Color.White, 1, GT.Color.White, 0, 0, this.displayN18.Width, this.displayN18.Height);

			this.gyro.Calibrate();
			this.gyro.MeasurementComplete += this.MeasurementComplete;
			this.gyro.StartTakingMeasurements();

			this.timer = new GT.Timer(2000);
			this.timer.Tick += this.TimerTick;
			this.timer.Start();
		}

		void MeasurementComplete(Gyro sender, Gyro.MeasurementCompleteEventArgs e) {
			this.x = e.X;
			this.y = e.Y;
			this.z = e.Z;
			this.temp = e.Temperature;
		}

		void TimerTick(GT.Timer sender) {
			this.displayN18.SimpleGraphics.DisplayRectangle(GT.Color.White, 1, GT.Color.White, 0, 0, 80, 56);

			this.displayN18.SimpleGraphics.DisplayText("X = " + this.x.ToString("F0"), Resources.GetFont(Resources.FontResources.NinaB), GT.Color.Black, 0, 0);
			this.displayN18.SimpleGraphics.DisplayText("Y = " + this.y.ToString("F0"), Resources.GetFont(Resources.FontResources.NinaB), GT.Color.Black, 0, 14);
			this.displayN18.SimpleGraphics.DisplayText("Z = " + this.z.ToString("F0"), Resources.GetFont(Resources.FontResources.NinaB), GT.Color.Black, 0, 28);
			this.displayN18.SimpleGraphics.DisplayText("Temp = " + this.temp.ToString("F0"), Resources.GetFont(Resources.FontResources.NinaB), GT.Color.Black, 0, 42);
		}
	}
}

???

You guys need to check your product descriptions.

How is 0.5hz a fast refresh rate?!

@ wolfbuddy - The display on its own can refresh quite a bit faster than that, but when you combine it with other functions that rate goes down. Showing constantly changing data values is a task better suited to a bigger display.

I’m seeing the same thing using a Gyro with a Cerberus mainboard. All that is connected is the gyro and a motor controller. I’ve tried both sockets 1 & 2 with the same results. I’m playing around with using the gyro to keep a robot moving in a straight line, later I’ll look into adding a accelerometer for hopefully even better results.

@ Duke Nukem - Does the issue persist if you remove the motor driver and just have a plain gyro test?

@ John - If I remove the motor controller and just have the gyro connected, no problems, however the rover is upside down in a ditch on mars any suggestions on the best way to feed gyro data into a PI controller so I can control motor speeds to drive straight?

Anyone already have code for this so I don’t have to reinvent the wheel?

@ Duke Nukem - If you just connect the motor but don’t change the code, does it start failing again?

1 Like

@ John - Just add the motor driver on socket 4 and it runs fine. If I put a motorDriverL298.StopAll(); its fine, but as soon as I put in a motorDriverL298.SetSpeed(MotorDriverL298.Motor.Motor2, 0.7); I start getting errors after a couple iterations.

Here is what I’m trying to build. A prototype for series of robotic classes I’m thinking of teaching.

1 Like

@ Duke Nukem - It sounds like the motor driver or motor is introducing some noise that the gyro is sensitive to. If you set the speed without a motor connected, does the issue persist?

1 Like

@ John - Not the answer I wanted to hear, but I tried some motor powered unpowered tests and it would appear you are correct and its the motors that are blowing up the gyro. Maybe I just added a session on shielding to the course, or maybe I need to find a better chassis/motor setup, anyone have any suggestions and remember price matters here as this will be a kit each attendee buys for the course (ie a chassis, Gadgeteer components etc).

Maybe the noise is causing bad bits on the I2C bus. Try a slower clock?