Patm
Posts: 23
Joined: Thu Mar 22, 2018 3:19 am

wiringPi and I2C, stuck at sending blank read command

Fri Mar 30, 2018 4:31 pm

I'm working with an Si7021 and I'm able to read the temp and humidty no problem but I'm stuck at trying to read the serial number. The problem is that I think I'm supposed to send a blank read and I can't figure out how. I've attached the table showing how it's supposed to work. The whole procedure returns four bytes but I'm just trying to get the first two. I know I figured this out a decade or two ago but since I haven't done any I2C since then I've completely forgotten how to do it.

What I'm doing is basically

Code: Select all

I2CCmd.WriteByte(_deviceHandle, 0xFA);
I2CCmd.WriteByte(_deviceHandle, 0x0F);
byte1 = I2CCmd.ReadByte(_deviceHandle);
byte2 = I2CCmd.ReadByte(_deviceHandle);
serial1 = byte1 * 256 + byte2;
Debug.Print("Serial Number part1 0x{0:x}", serial1);
and I just get zeros. Looking at the datasheet table on how this is supposed to go it looks like I'm supposed to read the device once without getting anything and then twice more to get the data but when I do that I still get zeros. I'm missing something obvious!

Here's the table from the Datasheet
I2CProb.jpg
I2CProb.jpg (71.4 KiB) Viewed 2391 times

User avatar
joan
Posts: 14089
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: wiringPi and I2C, stuck at sending blank read command

Fri Mar 30, 2018 4:44 pm

For what it's worth this is how I do it (not wiringPi).

http://abyz.me.uk/rpi/pigpio/examples.h ... _Si7021_py

Patm
Posts: 23
Joined: Thu Mar 22, 2018 3:19 am

Re: wiringPi and I2C, stuck at sending blank read command

Fri Mar 30, 2018 5:23 pm

Your code works fine so I know the device isn't messed up. You made me realize I'm supposed to get 8 bytes, not four, with every second byte being the CRC. I changed the code to read 8 but I still get nothing but zeros in every byte.

I'm sure the WriteByte() and ReadByte() work properly or I wouldn't be getting any readings from the device...

I'm doing something dumb, I know it. Anyway, this is what I'm doing now for the first part of the serial number. Every byte is 0.

Code: Select all

		private int GetSerialNumber()
		{
			int[] bytes = new int[8];
			int serial1;

			I2CCmd.WriteByte(_deviceHandle, 0xFA);
			I2CCmd.WriteByte(_deviceHandle, 0x0F);
			for (int i = 0; i < 8; i++)
			{
				bytes[i] = I2CCmd.ReadByte(_deviceHandle);
				Debug.Print("Byte is {0:x}", bytes[i]);
			}

			serial1 = bytes[0] << 24 + bytes[2] << 16 + bytes[4] << 8 + bytes[6];
			Debug.Print("Serial Number part1 0x{0:x}", serial1);

			return serial1;
		}

User avatar
joan
Posts: 14089
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: wiringPi and I2C, stuck at sending blank read command

Fri Mar 30, 2018 5:47 pm

Some devices require multi-byte reads to be done as one start/stop condition. That may be the case here. Perhaps a SMBus read I2C block data command is needed.

Patm
Posts: 23
Joined: Thu Mar 22, 2018 3:19 am

Re: wiringPi and I2C, stuck at sending blank read command

Fri Mar 30, 2018 6:33 pm

Yes I think you're right - you just jogged a memory from long ago about that. I'll have to see if wiringPi does larger than 8 bit reads.

Patm
Posts: 23
Joined: Thu Mar 22, 2018 3:19 am

Re: wiringPi and I2C, stuck at sending blank read command

Fri Mar 30, 2018 6:49 pm

Yep. Just found it in the wiringPi source and it looks like he never developed I2C past 8 bit operations properly. I already knew his read 16 bit was incomplete as it didn't handle endian types. If I were a C programmer I'd fix it up and submit but I'm not...

Maybe I'll have a go at pigpio since it seems to handle the block reads.

User avatar
joan
Posts: 14089
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: wiringPi and I2C, stuck at sending blank read command

Fri Mar 30, 2018 7:27 pm

Patm wrote:
Fri Mar 30, 2018 6:49 pm
Yep. Just found it in the wiringPi source and it looks like he never developed I2C past 8 bit operations properly. I already knew his read 16 bit was incomplete as it didn't handle endian types. If I were a C programmer I'd fix it up and submit but I'm not...

Maybe I'll have a go at pigpio since it seems to handle the block reads.
You can roll your own in Python to do the raw reads. I have posted Python code in the past which just reads/writes directly to /dev/i2c-0 or /dev/i2c-1.

User avatar
joan
Posts: 14089
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: wiringPi and I2C, stuck at sending blank read command

Fri Mar 30, 2018 7:29 pm

Python raw I2C read/write.

Code: Select all

#!/usr/bin/env python

import io
import fcntl
import sys

# i2c_raw.py
# 2016-02-26
# Public Domain

I2C_SLAVE=0x0703

if sys.hexversion < 0x03000000:
   def _b(x):
      return x
else:
   def _b(x):
      return x.encode('latin-1')

class i2c:

   def __init__(self, device, bus):

      self.fr = io.open("/dev/i2c-"+str(bus), "rb", buffering=0)
      self.fw = io.open("/dev/i2c-"+str(bus), "wb", buffering=0)

      # set device address

      fcntl.ioctl(self.fr, I2C_SLAVE, device)
      fcntl.ioctl(self.fw, I2C_SLAVE, device)

   def write(self, data):
      print(type(data))
      if type(data) is list:
         data = bytearray(data)
      elif type(data) is str:
         data = _b(data)
      self.fw.write(data)

   def read(self, count):
      return self.fr.read(count)

   def close(self):
      self.fw.close()
      self.fr.close()

if __name__ == "__main__":

   import time
   import i2c_raw

   dev = i2c_raw.i2c(0x32, 1) # device 0x32, bus 1

   dev.write([10, 1, 2, 3, ord('B'), ord('E'), ord('E'), ord('F')])
   dev.write(b"\x0a\x01\x02\x03BEEF")
   dev.write("\x0a\x01\x02\x03BEEF")

   dev.close()

Patm
Posts: 23
Joined: Thu Mar 22, 2018 3:19 am

Re: wiringPi and I2C, stuck at sending blank read command

Fri Mar 30, 2018 9:08 pm

I'm using C# with Winforms so python is not an option. I've used python in the past with some success but honestly I just can't stand the language and would end up shooting _self before I came close to finishing.

User avatar
joan
Posts: 14089
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: wiringPi and I2C, stuck at sending blank read command

Fri Mar 30, 2018 9:12 pm

Patm wrote:
Fri Mar 30, 2018 9:08 pm
I'm using C# with Winforms so python is not an option. I've used python in the past with some success but honestly I just can't stand the language and would end up shooting _self before I came close to finishing.
My mistake, I thought you were using the wiringPi Python module.

Patm
Posts: 23
Joined: Thu Mar 22, 2018 3:19 am

Re: wiringPi and I2C, stuck at sending blank read command

Fri Mar 30, 2018 10:34 pm

Well thanks for trying to help. You did identify the problem.

I used danriches/WiringPi.Net wrapper to figure out how to use the C library then I was expanding from there until I hit this limitation of wiringPi.

I don't see any C# wrappers for pigpio but if it can be done for wiringpi (and it was way easier than I thought) then maybe I can figure one out for pigpio too.

Patm
Posts: 23
Joined: Thu Mar 22, 2018 3:19 am

Re: wiringPi and I2C, stuck at sending blank read command

Sat Mar 31, 2018 4:10 am

Well, it's working. With simple dllimport() work I've got gpioInitialise() and i2cOpen() working. The only problem is that pesky root privileges problem. I can build remotely and run locally with sudo but can't use MonoRemoteDebugger because it's not root.

I keep reading everywhere that this problem of having to be root to access gpio was solved but I guess not.

edit: Actually, it wasn't a problem when doing this with wiringPi. I guess it's something to do with pigpio or I'm missing a step.

Patm
Posts: 23
Joined: Thu Mar 22, 2018 3:19 am

Re: wiringPi and I2C, stuck at sending blank read command

Sat Mar 31, 2018 4:55 am

Well I figured out that I was importing from the wrong library. instead of libpigpio.so I'm thinking it should be libpigpio_if2. Just have to figure out how to initialise the system since gpioinitialise() (or whatever the name was) doesn't exist in the new library. I get negative results from pigpio_start and i2c_open regardless of whether I use sudo or not whereas I'd fail without sudo and succeed with sudo using just libpigpio.so. At least now sudo doesn't seem to matter 8)

Patm
Posts: 23
Joined: Thu Mar 22, 2018 3:19 am

Re: wiringPi and I2C, stuck at sending blank read command

Sat Mar 31, 2018 5:12 am

TADA! Got it started. I'll post what I got then shut up until I have a full working C# wrapper (at least for I2C). Of course I was just looking for non negative return values so I probably have lots more to figure out but it's a start!

In form_load I use this:

Code: Select all

			_piHandle = Init.pigpio_start(null,null);
			Debug.Print("pigpio_start says {0}", _piHandle);


			_deviceHandle = I2CCmd.i2c_open(_piHandle, 1, 0x40, 0);
			Debug.Print("Handle is {0}", _deviceHandle);
And in another referenced project I have this:

Code: Select all

using System.Runtime.InteropServices;

namespace pipgio
{
	public class Init
	{
		[DllImport("libpigpiod_if2.so", EntryPoint = "pigpio_start")]     //This is an example of how to call a method / function in a c library from c#
		public static extern int pigpio_start(char[] addrStr, char[] portStr);

	}
	public class I2CCmd
	{
		[DllImport("libpigpiod_if2.so", EntryPoint = "i2c_open")]     //This is an example of how to call a method / function in a c library from c#
		public static extern int i2c_open(int pi, uint i2c_bus, uint i2c_addr, uint i2c_flags);
	}
}
I'm a happy camper. No sudo required.

P.S. I have to figure out how to properly convert "int pigpio_start(char *addrStr, char *portStr);" to c#. I'm just guessing char[] but then supply nulls. Hmmm, maybe "&addreStr, &portStr" with both of those being strings in C#?

Patm
Posts: 23
Joined: Thu Mar 22, 2018 3:19 am

Re: wiringPi and I2C, stuck at sending blank read command

Sat Mar 31, 2018 7:48 am

Found it. char * buf becomes [MarshalAs(UnmanagedType.LPStr)] string buf

Patm
Posts: 23
Joined: Thu Mar 22, 2018 3:19 am

Re: wiringPi and I2C, stuck at sending blank read command

Sat Mar 31, 2018 3:34 pm

Lol, nothing is ever easy. Seems something as simple as passing two bytes is turning into a major endeavor thanks to that char*. I can find lots of links telling me to use the MarshallAs bit but not a single one that tells me how to pass two bytes to it without just ending up with multi-character string representations of their decimal values.

Return to “Other programming languages”