Trinket sending messages to Raspberry Pi via I2C


8 posts
by DeckerEgo » Tue Jan 21, 2014 5:08 am
Just to try things out, I'm attempting to send messages from an Adafruit Trinket over to a Raspberry Pi via I2C. I'm using WiringPi2 for the Python side on the Raspberry Pi, and TinyWireM on the Arduino side for the Trinket.

I've connected pin0 of the Trinket (data) to pin3 of the Pi (SDA), pin2 of the Trinket (clock) to pin 5 of the Pi (SCL), and GND of the Trinket to pin6 of the Pi (ground).

Python side is:
Code: Select all
import wiringpi2

fd = wiringpi2.wiringPiI2CSetup(0x70)
print fd

while 1 > 0:
  ret = -1
  while ret <= 0:
    ret = wiringpi2.wiringPiI2CRead(fd)

  print ret


Trinket side is:
Code: Select all
#include <TinyWireM.h>                  // I2C Master lib for ATTinys which use USI

int led = 1;

void setup(){
  TinyWireM.begin();                    // initialize I2C lib
  pinMode(led, OUTPUT);
}

void loop() {
  digitalWrite(led, HIGH);
   
  TinyWireM.beginTransmission(0x70);
  digitalWrite(led, LOW);

  TinyWireM.write(0x07);
  digitalWrite(led, HIGH);

  TinyWireM.endTransmission();
  digitalWrite(led, LOW);
 
  delay(500);
  TinyWireM.begin();
}


I see largely garbage when using ic2detect - all the addresses fill up with sequential values:
Code: Select all
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
10: 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
20: 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
30: 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
40: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
50: 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
60: 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
70: 70 71 72 73 74 75 76 77                         


Python will occasionally see a 0 or a 255, but not the datagram being sent. Any ideas? What am I messing up?
User avatar
Posts: 18
Joined: Sun Oct 27, 2013 2:08 pm
by Douglas6 » Tue Jan 21, 2014 6:16 am
I haven't tried this, so this is just theory, but I2C requires a master and a slave. The Pi can only be a master, so you'll need to use TinyWireS on the Trinket, and the Pi will need to initiate communications (do the writing and reading).
User avatar
Posts: 3807
Joined: Sat Mar 16, 2013 5:34 am
Location: Chicago, IL
by DeckerEgo » Tue Jan 21, 2014 6:24 am
Douglas6 wrote:The Pi can only be a master, so you'll need to use TinyWireS on the Trinket

Interesting - I didn't realize that. I'll try out TinyWireS and see if I can get that to work. Thanks!
User avatar
Posts: 18
Joined: Sun Oct 27, 2013 2:08 pm
by Douglas6 » Tue Jan 21, 2014 6:54 am
You ARE using a 3v3 Trinket I trust....
User avatar
Posts: 3807
Joined: Sat Mar 16, 2013 5:34 am
Location: Chicago, IL
by DeckerEgo » Tue Jan 21, 2014 11:29 am
Douglas6 wrote:You ARE using a 3v3 Trinket I trust....

Dangit... no. I'm glad you asked, because it does appear I grabbed a 5V one instead of the 3.3V one. Next time I shouldn't try smashing things together at 1 AM...
User avatar
Posts: 18
Joined: Sun Oct 27, 2013 2:08 pm
by Douglas6 » Sun Jan 26, 2014 4:22 pm
I've been meaning to give this a try. The following code works pretty well to read an analog pin on the Trinket from the Pi via I2C. I used a 3v3 Trinket running at 8 mHz and Rambo's TinyWireS library. Here's the Trinket code
Code: Select all
#include <TinyWireS.h>

#define I2C_SLAVE_ADDRESS 0x04

byte reg[] = {0x00, 0x00};
byte reg_idx = 0;

void onRequest()
{
  TinyWireS.send(reg[reg_idx]);
  reg_idx = (reg_idx == 1) ? 0 : 1;
}

void setup()
{
    TinyWireS.begin(I2C_SLAVE_ADDRESS);
    TinyWireS.onRequest(onRequest);
}

void loop()
{
    int a2 = analogRead(2);
    reg[0] = lowByte(a2);
    reg[1] = highByte(a2);

    TinyWireS_stop_check();
}

And on the Pi:
Code: Select all
import smbus
import time

DEV_ADDR = 0x04

bus = smbus.SMBus(1)
reads = 0
errs = 0

while True:
    reads += 1
    try:
        a_val = bus.read_word_data(DEV_ADDR, 0)
        print("Read value [%s]; no. of reads [%s]; no. of errors [%s]" % (a_val, reads, errs))
    except Exception as ex:
        errs += 1
        print("Exception [%s]" % (ex))

    time.sleep(0.01)

And some sample output:
Code: Select all
read value [0]; no. of reads [177921]; no. of errors [11]
read value [1]; no. of reads [177922]; no. of errors [11]
read value [3]; no. of reads [177923]; no. of errors [11]
read value [6]; no. of reads [177924]; no. of errors [11]
read value [10]; no. of reads [177925]; no. of errors [11]
read value [12]; no. of reads [177926]; no. of errors [11]
read value [15]; no. of reads [177927]; no. of errors [11]
read value [18]; no. of reads [177928]; no. of errors [11]
read value [22]; no. of reads [177929]; no. of errors [11]
read value [28]; no. of reads [177930]; no. of errors [11]
read value [36]; no. of reads [177931]; no. of errors [11]
read value [46]; no. of reads [177932]; no. of errors [11]
read value [59]; no. of reads [177933]; no. of errors [11]
read value [70]; no. of reads [177934]; no. of errors [11]
read value [82]; no. of reads [177935]; no. of errors [11]
read value [94]; no. of reads [177936]; no. of errors [11]
read value [107]; no. of reads [177937]; no. of errors [11]
read value [120]; no. of reads [177938]; no. of errors [11]
read value [134]; no. of reads [177939]; no. of errors [11]
read value [148]; no. of reads [177940]; no. of errors [11]
read value [162]; no. of reads [177941]; no. of errors [11]
read value [175]; no. of reads [177942]; no. of errors [11]
read value [190]; no. of reads [177943]; no. of errors [11]
read value [207]; no. of reads [177944]; no. of errors [11]
read value [218]; no. of reads [177945]; no. of errors [11]
read value [232]; no. of reads [177946]; no. of errors [11]
read value [244]; no. of reads [177947]; no. of errors [11]
read value [259]; no. of reads [177948]; no. of errors [11]
read value [273]; no. of reads [177949]; no. of errors [11]
read value [286]; no. of reads [177950]; no. of errors [11]
read value [300]; no. of reads [177951]; no. of errors [11]
read value [314]; no. of reads [177952]; no. of errors [11]
read value [330]; no. of reads [177953]; no. of errors [11]
read value [344]; no. of reads [177954]; no. of errors [11]
read value [358]; no. of reads [177955]; no. of errors [11]
read value [371]; no. of reads [177956]; no. of errors [11]
read value [387]; no. of reads [177957]; no. of errors [11]
read value [400]; no. of reads [177958]; no. of errors [11]
read value [413]; no. of reads [177959]; no. of errors [11]
read value [425]; no. of reads [177960]; no. of errors [11]
read value [436]; no. of reads [177961]; no. of errors [11]
read value [448]; no. of reads [177962]; no. of errors [11]
read value [459]; no. of reads [177963]; no. of errors [11]
read value [471]; no. of reads [177964]; no. of errors [11]
read value [481]; no. of reads [177965]; no. of errors [11]
read value [497]; no. of reads [177966]; no. of errors [11]
read value [510]; no. of reads [177967]; no. of errors [11]
read value [524]; no. of reads [177968]; no. of errors [11]
read value [536]; no. of reads [177969]; no. of errors [11]
read value [550]; no. of reads [177970]; no. of errors [11]
read value [562]; no. of reads [177971]; no. of errors [11]
read value [575]; no. of reads [177972]; no. of errors [11]
read value [587]; no. of reads [177973]; no. of errors [11]
read value [598]; no. of reads [177974]; no. of errors [11]
User avatar
Posts: 3807
Joined: Sat Mar 16, 2013 5:34 am
Location: Chicago, IL
by DeckerEgo » Mon Jan 27, 2014 4:40 am
Douglas6 wrote:I've been meaning to give this a try. The following code works pretty well to read an analog pin on the Trinket from the Pi via I2C.


This is exactly what I was looking for! I'm ripping a 3.3V Trinket out of an old project to try this out now ;) I was working on building my own logic inverter to convert RS232 into UART, which was kinda fun in and of itself, but I definitely will try this out as well. I dig this idea of having a Trinket operate as an analog co-pilot.

Thanks!
User avatar
Posts: 18
Joined: Sun Oct 27, 2013 2:08 pm
by Douglas6 » Mon Jan 27, 2014 5:17 am
It would be interesting to see if one could use the 'cmd' parameter of the SMBus read command to select between the A2 and A3 pins by implementing an onReceive() callback.

A word of caution: both A2 and A3 (#4 and #3) pins are used during USB programming, you may have to disconnect them from the circuit while uploading.
User avatar
Posts: 3807
Joined: Sat Mar 16, 2013 5:34 am
Location: Chicago, IL