Strange data received from SRF02 I2C - Netduino Plus 2 (and Netduino Plus 1) - Netduino Forums
   
Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

Strange data received from SRF02 I2C

Netduino Plus SRF02 Devantech I2C

Best Answer hanzibal, 25 June 2013 - 06:01 PM

Yes, two 10k resistors i parallel should correspond to a single 5k resistor. Well, it was just a thought.

 

Looking again at your code and comparing to the user manual you referred to, it seems you're are doing the reads wrong. You should read location 2 and 3 separately to get the high and low byte respectively. As it is now, you issue a series of four transactions where the read buffer gets overwritten by the the second read transaction. Your read buffer is 2 bytes but I think it only need be one byte since first you should read the high byte and then you read the low byte (the order does not seem to matter).

 

Also, I believe the location counter (address counter) auto-increments for each read performed so you could probably do something like this instead (here, the read buffer is still 2 bytes long):

xActions = new I2CDevice.I2CTransaction[]{	I2CDevice.CreateWriteTransaction(new byte[] { 0x02 }),	I2CDevice.CreateReadTransaction(RegisterValue),}int c = srf02.Execute(xActions, 1000);Debug.Assert(c > 0, "I2C write/read failed!");int val = (RegisterValue[0] << 8)|RegisterValue[1];

As you know, the Netduino is 5V tolerant and I wonder if the the LLC is really necessary - have you tried without it?

Go to the full post


  • Please log in to reply
7 replies to this topic

#1 TankMaster

TankMaster

    New Member

  • Members
  • Pip
  • 9 posts

Posted 23 June 2013 - 01:01 PM

I have been looking through the forum to find a solution, but with no success... This is my issue, for some reason I get this strange data stream output when communicating with a Devantech SRF02 over I2C:

Waving my hand in front of it:Distance in inches : 25856Distance in centimeters : 512Distance in microseconds : 43267Distance in inches : 15616Distance in centimeters : 39936Distance in microseconds : 36355Distance in inches : 21760Distance in centimeters : 5376Distance in microseconds : 18947Distance in inches : 1792Distance in centimeters : 7424Distance in microseconds : 9731Distance in inches : 25856Distance in centimeters : 5376Distance in microseconds : 23811Distance in inches : 3072Distance in centimeters : 7936Distance in microseconds : 37379Distance in inches : 25856Distance in centimeters : 7936Distance in microseconds : 38403Distance in inches : 2048Distance in centimeters : 39936Distance in microseconds : 13059Distance in inches : 22528Distance in centimeters : 1024Distance in microseconds : 28931Distance in inches : 25856Distance in centimeters : 39680Distance in microseconds : 34819Distance in inches : 26112Distance in centimeters : 4352Distance in microseconds : 17667Distance in inches : 2048Distance in centimeters : 56832Distance in microseconds : 60931Distance in inches : 25600Distance in centimeters : 39424Distance in microseconds : 15107Distance in inches : 25856Distance in centimeters : 46848Distance in microseconds : 34819Distance in inches : 3072Distance in centimeters : 39936Distance in microseconds : 41475Distance in inches : 15616Distance in centimeters : 39680Distance in microseconds : 35587Distance in inches : 25856Distance in centimeters : 7936Distance in microseconds : 10499Distance in inches : 15616Distance in centimeters : 39936Distance in microseconds : 20227Not waving my hand in front of it:Distance in inches : 15616Distance in centimeters : 768Distance in microseconds : 44547Distance in inches : 15616Distance in centimeters : 512Distance in microseconds : 32259Distance in inches : 25856Distance in centimeters : 512Distance in microseconds : 38915Distance in inches : 25856Distance in centimeters : 512Distance in microseconds : 51971Distance in inches : 25856Distance in centimeters : 39680Distance in microseconds : 38147Distance in inches : 25856Distance in centimeters : 768Distance in microseconds : 41475Distance in inches : 25856Distance in centimeters : 512Distance in microseconds : 32259Distance in inches : 15616Distance in centimeters : 39936Distance in microseconds : 46339Distance in inches : 25856Distance in centimeters : 40192Distance in microseconds : 38147Distance in inches : 15616Distance in centimeters : 512Distance in microseconds : 41987Distance in inches : 25856Distance in centimeters : 40192Distance in microseconds : 50947Distance in inches : 15616Distance in centimeters : 512Distance in microseconds : 56067Distance in inches : 15616Distance in centimeters : 40192Distance in microseconds : 43779Distance in inches : 15872Distance in centimeters : 512Distance in microseconds : 24067Distance in inches : 15616Distance in centimeters : 40192Distance in microseconds : 36099Distance in inches : 15616Distance in centimeters : 40192Distance in microseconds : 41475Distance in inches : 25856Distance in centimeters : 768Distance in microseconds : 46595Distance in inches : 25856Distance in centimeters : 1024Distance in microseconds : 43779Distance in inches : 15616Distance in centimeters : 39680Distance in microseconds : 33027Distance in inches : 15616Distance in centimeters : 39936Distance in microseconds : 27139Distance in inches : 15616Distance in centimeters : 39680Distance in microseconds : 33027Distance in inches : 15616Distance in centimeters : 39936Distance in microseconds : 20739Distance in inches : 15616Distance in centimeters : 39680Distance in microseconds : 33027Distance in inches : 15616Distance in centimeters : 39936Distance in microseconds : 33027Distance in inches : 15616Distance in centimeters : 39936Distance in microseconds : 27139Distance in inches : 15616Distance in centimeters : 39936Distance in microseconds : 27139Distance in inches : 15616Distance in centimeters : 39936Distance in microseconds : 20227Distance in inches : 15616Distance in centimeters : 39936Distance in microseconds : 30979Distance in inches : 15616Distance in centimeters : 39680Distance in microseconds : 24067Distance in inches : 15616Distance in centimeters : 39680Distance in microseconds : 25347Distance in inches : 15616Distance in centimeters : 39680Distance in microseconds : 43267Distance in inches : 15616Distance in centimeters : 39680Distance in microseconds : 18179Distance in inches : 15616Distance in centimeters : 39680Distance in microseconds : 18179Distance in inches : 15616Distance in centimeters : 39936Distance in microseconds : 24579Distance in inches : 15616Distance in centimeters : 39680Distance in microseconds : 30467

I have it connected to my Netduino Plus through a breadboard, here is the connection scheme: Attached File  UltrasonicRangeFinderSensor_SRF02_I2C_bb.png   248.01KB   0 downloads And some links for the components: Devantech SRF02 I2C documentation, Adafruit Logic Level Converter with 10k pull-ups. And as well the code I'm using, SDK 4.2 is used. BTW is the value of the Execute methods timeout really needed to be 1000 ms when I have the Thread.Sleep method at 80 ms before reading from the register of the device? I have as well set the I2C clock to 100kHz, but still getting the same readings with 400kHz.

using System;using System.IO.Ports;using System.Threading;using Microsoft.SPOT;using Microsoft.SPOT.Hardware;using SecretLabs.NETMF.Hardware;using SecretLabs.NETMF.Hardware.NetduinoPlus;namespace UltrasonicRangeFinderSensor{	public class I2C_SRF02	{		private static InterruptPort button = new InterruptPort(			Pins.ONBOARD_SW1, true, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeLevelLow);		private static I2CDevice.Configuration con = new I2CDevice.Configuration(0x70, 400); // Most significant bits, 7-bit		private static I2CDevice srf02 = new I2CDevice(con);		// First transaction is writing the "read command"		// Second transaction is reading the data		private static I2CDevice.I2CTransaction[] xActions;		// create read buffer to read the register		private static byte[] RegisterValue = new byte[2];				  private static System.Text.UTF8Encoding encoder = new System.Text.UTF8Encoding();		private static byte[] queryResult = new byte[2];		enum RealResultType : byte		 {			 Inch = 0x50,			Centimeters = 0x51,			Microseconds = 0x52		};		public static void Main()		{			using (srf02)			{				button.OnInterrupt += button_OnInterrupt;				Thread.Sleep(Timeout.Infinite);			}		}		private static void button_OnInterrupt(uint port, uint state, DateTime time)		{			getRangeResults();			button.ClearInterrupt();		}		private static void getRangeCommand(RealResultType resultType)		{			xActions = new I2CDevice.I2CTransaction[1];			// Issuing a ranging			xActions[0] = I2CDevice.CreateWriteTransaction(new byte[] { 0x00, (byte)resultType });			// if the execute command returns zero, the transaction failed (this			// is a good check to make sure that you are communicating with the device correctly			// and don’t have a wiring issue or other problem with the I2C device)			if (srf02.Execute(xActions, 1000) == 0)			{				Debug.Print("Failed to perform I2C transaction");			}			Thread.Sleep(80); // Letting the N+ sleep until the ranging is done			xActions = new I2CDevice.I2CTransaction[4];			// Setting the register pointer to echo #1 register to retrieve the result			// and Requesting the result of the ranging			xActions[0] = I2CDevice.CreateWriteTransaction(new byte[] { 0x02 });			xActions[1] = I2CDevice.CreateReadTransaction(RegisterValue);			xActions[2] = I2CDevice.CreateWriteTransaction(new byte[] { 0x03 });			xActions[3] = I2CDevice.CreateReadTransaction(RegisterValue);						if (srf02.Execute(xActions, 1000) == 0)			{				Debug.Print("Failed to perform I2C transaction");			}			else			{				if (resultType.Equals(RealResultType.Centimeters))				{					Debug.Print("Distance in centimeters : " + (ushort)((RegisterValue[0] << 8) | RegisterValue[1]));				}				else if (resultType.Equals(RealResultType.Inch))				{					Debug.Print("Distance in inches : " + (ushort)((RegisterValue[0] << 8) | RegisterValue[1]));				}				else if (resultType.Equals(RealResultType.Microseconds))				{					Debug.Print("Distance in microseconds : " + (ushort)((RegisterValue[0] << 8) | RegisterValue[1]));				}			}		}		private static void getRangeResults()		{			getRangeCommand(RealResultType.Inch);			Thread.Sleep(100);			getRangeCommand(RealResultType.Centimeters);			Thread.Sleep(100);			getRangeCommand(RealResultType.Microseconds);			Thread.Sleep(100);		}	}}

Could it be that I have damaged my board in some way? Because before without knowing that the pins are 5V tolerant but the logic is only 3.3V tolerant I only used pull-ups and not the logic level converter, so I had 5V directly to the analog pins... Or has something happened to my SRF02? Static electricity? Rather a newbie at I2C communication, most of the code is based on examples I have found here and on a variety of wikis. Regards, TM



#2 hanzibal

hanzibal

    Advanced Member

  • Members
  • PipPipPip
  • 1287 posts
  • LocationSweden

Posted 24 June 2013 - 11:13 PM

Perhaps you got the msb/lsb conversion wrong or the values are signed? The ratio between inches and centimetres seem correct most of the time. I trust the I2C pull-up resistors are in place. Got any pins floating?

#3 TankMaster

TankMaster

    New Member

  • Members
  • Pip
  • 9 posts

Posted 25 June 2013 - 10:46 AM

Perhaps you got the msb/lsb conversion wrong or the values are signed? The ratio between inches and centimetres seem correct most of the time. I trust the I2C pull-up resistors are in place. Got any pins floating?

 

I think the bitwise operations are right, not so much experience from it but the examples I have found used the one I have. The data result is 16 bit unsigned, so it must be that bitwise operation above that is right... The Arduino equivalent I found where this: http://arduino.cc/en...urceblock&num=1

reading = Wire.read();  // receive high byte (overwrites previous reading)reading = reading << 8;    // shift high byte to be high 8 bitsreading |= Wire.read(); // receive low byte as lower 8 bits

The LLC has 10k pull-ups, and as an extra precaution I have now as well connected the remaining pins on the LLC to ground, but that didn't give any difference (which it shouldn't do right? As the lines are separated, or?).



#4 hanzibal

hanzibal

    Advanced Member

  • Members
  • PipPipPip
  • 1287 posts
  • LocationSweden

Posted 25 June 2013 - 11:36 AM

I agree, the byte order is equal to that of the Arduino code.

 

In my experience floating pins can sometimes result in strange phenomena and I try to avoid them even if it theoretically shouldn't matter. I normally use 100k pull-downs on unused pins though.

 

You could try using stronger I2C pull-ups, say 4k7 as see if that helps.



#5 TankMaster

TankMaster

    New Member

  • Members
  • Pip
  • 9 posts

Posted 25 June 2013 - 03:11 PM

I agree, the byte order is equal to that of the Arduino code.

 

In my experience floating pins can sometimes result in strange phenomena and I try to avoid them even if it theoretically shouldn't matter. I normally use 100k pull-downs on unused pins though.

 

You could try using stronger I2C pull-ups, say 4k7 as see if that helps.

 

Okay, but how do I do that when I have the 10k's already on the LLC board? I tried to add resistors in parallel connected as pull-ups, together with the wire from/to the LLC on each voltage side, to achieve in theory an approx. 4.7k ohm resistor for SDA & SDL on both of the voltage sides. Is this not correct? I still get the wrong output data with this setup... Feels like I'm walking in the mist right now ^^



#6 hanzibal

hanzibal

    Advanced Member

  • Members
  • PipPipPip
  • 1287 posts
  • LocationSweden

Posted 25 June 2013 - 06:01 PM   Best Answer

Yes, two 10k resistors i parallel should correspond to a single 5k resistor. Well, it was just a thought.

 

Looking again at your code and comparing to the user manual you referred to, it seems you're are doing the reads wrong. You should read location 2 and 3 separately to get the high and low byte respectively. As it is now, you issue a series of four transactions where the read buffer gets overwritten by the the second read transaction. Your read buffer is 2 bytes but I think it only need be one byte since first you should read the high byte and then you read the low byte (the order does not seem to matter).

 

Also, I believe the location counter (address counter) auto-increments for each read performed so you could probably do something like this instead (here, the read buffer is still 2 bytes long):

xActions = new I2CDevice.I2CTransaction[]{	I2CDevice.CreateWriteTransaction(new byte[] { 0x02 }),	I2CDevice.CreateReadTransaction(RegisterValue),}int c = srf02.Execute(xActions, 1000);Debug.Assert(c > 0, "I2C write/read failed!");int val = (RegisterValue[0] << 8)|RegisterValue[1];

As you know, the Netduino is 5V tolerant and I wonder if the the LLC is really necessary - have you tried without it?



#7 TankMaster

TankMaster

    New Member

  • Members
  • Pip
  • 9 posts

Posted 25 June 2013 - 06:34 PM

Yes, two 10k resistors i parallel should correspond to a single 5k resistor. Well, it was just a thought.

 

Looking again at your code and comparing to the user manual you referred to, it seems you're are doing the reads wrong. You should read location 2 and 3 separately to get the high and low byte respectively. As it is now, you issue a series of four transactions where the read buffer gets overwritten by the the second read transaction. Your read buffer is 2 bytes but I think it only need be one byte since first you should read the high byte and then you read the low byte (the order does not seem to matter).

 

Also, I believe the location counter (address counter) auto-increments for each read performed so you could probably do something like this instead (here, the read buffer is still 2 bytes long):

xActions = new I2CDevice.I2CTransaction[]{	I2CDevice.CreateWriteTransaction(new byte[] { 0x02 }),	I2CDevice.CreateReadTransaction(RegisterValue),}int c = srf02.Execute(xActions, 1000);Debug.Assert(c > 0, "I2C write/read failed!");int val = (RegisterValue[0] << 8)|RegisterValue[1];

As you know, the Netduino is 5V tolerant and I wonder if the the LLC is really necessary - have you tried without it?

 

Hmm, seems like I have not understood this from the beginning... So LSB shall be skipped? Then why is both MSB and LSB available (Range High byte/MSB and Range Low byte/LSB)... I'm getting correct results now when only reading the MSB and doing the shift etc with it :) Why did you changed so that 2 is the number that means that the I2C operation has failed? I know that the N+ is 5V tolerant, but only the pins and the circuit board in my interpretation, I have never understood that the logic supports it as well...

 

Thanks for your time and help! :)



#8 hanzibal

hanzibal

    Advanced Member

  • Members
  • PipPipPip
  • 1287 posts
  • LocationSweden

Posted 25 June 2013 - 07:07 PM

You're not skipping LSB, you read both MSB and LSB as two consecutive bytes - because they are one byte each, only when combined can they form the 16 bit number that represent the reading. About the "c == 2", I changed that shortly afterwards since it was a mistake, sorry for the confusion it may have caused. Fortunately, you quoted the correct version. As for the LLC, you usually only need that when talking to something that either 1) uses less than 3V3 and is intolerant of that or something that 2) uses something in between of 3V3 and 5V which doesn't think 3V3 qualifies as a logic high or 3) something that uses more than 5V as it could harm the Netduino. A logic low is normally ground and thus no problems with that. In your case, the Netduino will have no problem with the I2C lines being pulled up to 5V.





Also tagged with one or more of these keywords: Netduino Plus, SRF02, Devantech, I2C

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.