I tried to do this first in Python and the problem was always present - meaning the LSB always went from 0 to 127 twice before the MSB had 1 added to it. The I found some posts on the internet stating that Python was too slow for it to be able to use I2C correctly so I re-wrote everything in C++. I got far better results but there´s the occasional hicup.
The connections are pretty simple: The Trinket is being powered by the RPi using one of the ground pins and one of the 5v pins (the Trinket´s on board regulators get it down to 3v3). Then 2 simple jumper wires connec SDA and SCL on the RPi to the corresponding pins on the Trinket. The trinket is mounted on a protoboard and the Rpi is also connected using the protoboard and a T-Cobbler. The T-cobbler is connected to the RPi with a 40 wire flat cable.
This is the code used for the Trinket:
Code: Select all
#include <TinyWireS.h>
#define I2C_SLAVE_ADDRESS 0x04
byte reg[] = {0x00, 0x00};
byte reg_idx = 0;
int ticks = 0;
int number = 0;
void onRequest()
{
TinyWireS.send(reg[reg_idx]);
reg_idx = (reg_idx == 1) ? 0 : 1;
}
void onReceive(uint8_t dataSize)
{
if (dataSize < 1)
return;
while(TinyWireS.available())
{
number = TinyWireS.receive();
if (number == 1)
{
//int a2 = analogRead(2);
int a2 = ticks;
reg[0] = lowByte(a2);
reg[1] = highByte(a2);
//reg[0] = a2 & 255;
//reg[1] = a2 >> 8;
reg_idx = 0;
ticks++;
if (ticks > 1023)
ticks = 0;
}
}
}
void setup()
{
TinyWireS.begin(I2C_SLAVE_ADDRESS);
TinyWireS.onRequest(onRequest);
TinyWireS.onReceive(onReceive);
}
void loop()
{
TinyWireS_stop_check();
}
Code: Select all
/******************************************************************************
i2ctest.cpp
Raspberry Pi I2C interface demo
Byron Jacquot @ SparkFun Electronics>
4/2/2014
https://github.com/sparkfun/Pi_Wedge
A brief demonstration of the Raspberry Pi I2C interface, using the SparkFun
Pi Wedge breakout board.
Resources:
This example makes use of the Wiring Pi library, which streamlines the interface
the the I/O pins on the Raspberry Pi, providing an API that is similar to the
Arduino. You can learn about installing Wiring Pi here:
http://wiringpi.com/download-and-install/
The I2C API is documented here:
https://projects.drogon.net/raspberry-pi/wiringpi/i2c-library/
The init call returns a standard file descriptor. More detailed configuration
of the interface can be performed using ioctl calls on that descriptor.
See the wiringPi I2C implementation (wiringPi/wiringPiI2C.c) for some examples.
Parameters configurable with ioctl are documented here:
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/i2c/dev-interface
Hardware connections:
This file interfaces with the SparkFun MCP4725 breakout board:
https://www.sparkfun.com/products/8736
The board was connected as follows:
(Raspberry Pi)(MCP4725)
GND -> GND
3.3V -> Vcc
SCL -> SCL
SDA -> SDA
An oscilloscope probe was connected to the analog output pin of the MCP4725.
To build this file, I use the command:
> g++ i2ctest.cpp -lwiringPi
Then to run it, first the I2C kernel module needs to be loaded. This can be
done using the GPIO utility.
> gpio load i2c 400
> ./a.out
This will run the MCP through its output range several times. A rising
sawtooth will be seen on the analog output.
Development environment specifics:
Tested on Raspberry Pi V2 hardware, running Raspbian.
Building with GCC 4.6.3 (Debian 4.6.3-14+rpi1)
This code is beerware; if you see me (or any other SparkFun employee) at the
local, and you've found our code helpful, please buy us a round!
Distributed as-is; no warranty is given.
******************************************************************************/
#include <iostream>
#include <errno.h>
#include <wiringPiI2C.h>
#include <unistd.h>
using namespace std;
int main()
{
int fd, result, l, h;
int num = 0;
int prevNum = 1023;
bool goOn = true;
int count = 10000;
int errors = 0;
// Initialize the interface by giving it an external device ID.
// The MCP4725 defaults to address 0x60.
//
// It returns a standard file descriptor.
//
fd = wiringPiI2CSetup(0x04);
cout << "Init result: "<< fd << endl;
while (count >= 0)
{
count--;
// I tried using the "fast write" command, but couldn't get it to work.
// It's not entirely obvious what's happening behind the scenes as
// regards to endianness or length of data sent. I think it's only
// sending one byte, when we really need two.
//
// So instead I'm doing a 16 bit register access. It appears to
// properly handle the endianness, and the length is specified by the
// call. The only question was the register address, which is the
// concatenation of the command (010x = write DAC output)
// and power down (x00x = power up) bits.
//result = wiringPiI2CWriteReg16(fd, 0x40, (i & 0xfff) );
result = wiringPiI2CWrite(fd, 1);
if(result == -1)
{
cout << "Error sending. Errno is: " << errno << endl;
goOn = false;
}
else
{
//sleep(1);
l = wiringPiI2CRead(fd);
if(l == -1)
{
cout << "Error reading l. Errno is: " << errno << endl;
goOn = false;
}
h = wiringPiI2CRead(fd);
if(h == -1)
{
cout << "Error reading h. Errno is: " << errno << endl;
goOn = false;
}
num = (h * 256 + l);
cout << "Numero: " << num << " l: " << l << " h: " << h << endl;
if (prevNum != 1023 && num - prevNum != 1)
{
cout << "ERROR DE NUMERO!!!!!!!!!!!!!!!!!!!!" << endl;
//sleep(3);
errors++;
}
prevNum = num;
}
//sleep(1);
}
cout << errors;
}