9 years, 8 months ago.

I2C to control tiny with EA LPC4088

Hi all, I'm quite new on this forum, so yes you can call me a newbee in mbed development.

I have run in to trouble trying to control an ATtiny on I2C.

This is part of the code on the Tiny. When the Tiny receive command 0x00 it shall identify itself:

static void twi_callback(uint8_t buffer_size, volatile uint8_t input_buffer_length, const volatile uint8_t *input_buffer,
uint8_t volatile *output_buffer_length, volatile uint8_t *output_buffer)
{
	uint8_t input;
	uint8_t	command;
	uint8_t	io;

	//PORTB |= _BV(4);
	//led_timeout_command = LED_OFF_TIMEOUT;

	if(input_buffer_length < 1)
	return(build_reply(output_buffer_length, output_buffer, 0, 1, 0, 0));

	input	= input_buffer[0];
	command	= input & 0xf8;
	io		= input & 0x07;

	switch(command)
	{
		
		case(0x00):	// short / no-io
		{
			switch(io)
			{
				case(_identify):	// identify
				{
					LED_ON;
					struct
					{
						uint8_t id1, id2;
						uint8_t model, version, revision;
						uint8_t name[16];
					} reply =
					{
						0x4a, 0xfb,
						0x05, 0x01, 0x00,
						"attiny85",
					};
				    _delay_ms(10);
					LED_OFF;
					return(build_reply(output_buffer_length, output_buffer, input, 0, sizeof(reply), (uint8_t *)&reply));
					
				}

I tried this code in the mbed device (but i seem to get it wrong):

#include "mbed.h"
 

 
I2C i2c(p32, p31);
Serial pc(USBTX, USBRX); // tx, rx
 
const int addr = 0x10;
 
int main() {
    char cmd[12];
    while (1) {
        //cmd[0] = 0x01;
        //cmd[1] = 0x00;
        cmd[0] = 0x00;
        i2c.write(addr, cmd, 1);
 
        wait(0.5);
 
        cmd[0] = 0x00;
        i2c.write(addr, cmd, 1);
        i2c.read(addr, cmd, 12);
        
        for(int i=0;i<13;i++){
            pc.printf(cmd[i]);
            }
        wait(5.0);
        
    }
}

Can some friendly soul please show me how the i2C call is done right and how to present the result?

BR Johan

Hello again, Now I put in a very simple program in the tiny, like this:

#define F_CPU 8000000UL

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay_basic.h>
#include "usiTwiSlave.h"

#define I2C_SLAVE_ADDR  0x10
#define LED PB1

// Somewhere to store the values the master writes to i2c register 2 and 3.
static volatile uint8_t i2cReg2 = 0;
static volatile uint8_t i2cReg3 = 0;

// A callback triggered when the i2c master attempts to read from a register.
uint8_t i2cReadFromRegister(uint8_t reg)
{
	switch (reg)
	{
		case 0:
		return 10;
		case 1:
		return i2cReg2;
		case 2:
		return i2cReg3;
		default:
		return 0xff;
	}
}

// A callback triggered when the i2c master attempts to write to a register.
void i2cWriteToRegister(uint8_t reg, uint8_t value)
{
	switch (reg)
	{
		case 2:
		i2cReg2 = value;
		break;
		case 3:
		i2cReg3 = value;
		break;
	}
}

int main()
{
	// Set the LED pin as output.
	DDRB |= (1 << LED);

	usiTwiSlaveInit(I2C_SLAVE_ADDR, i2cReadFromRegister, i2cWriteToRegister);
	
	sei();

	while (1)
	{
		// This is a pretty pointless EXAMPLE which allows me to test writing to two i2c registers: the
		// LED is only lit if both registers have the same value.
		if (i2cReg2 == i2cReg3)
		PORTB |= 1 << LED;
		else
		PORTB &= ~(1 << LED);
	}
}

But still when I scan adresses i get answer with the arduino, but Not with the mbed device. Please Help, wher is it going wrong?

posted by Johan Svensson 01 Sep 2014

1 Answer

9 years, 8 months ago.

You seem to send two commands 0x00 before starting to receive. That causes problems when only one command is expected. Next you try to receive a 12byte message. However it looks like the tiny is building and sending a 21byte message as it sends the struct 'reply'.

Tried to change and now i get an answer, but it complains of unknown command.

1b 02 00 00 00 03 00 10 f0 ff 00 10 f0 ff 00 10 00 00 00 00 00 00 00

When running scanning function on an Arduino the device reply but also it go into the "_identify" loop.

So maybe I need to send the commands in another way.

Any thoughts or tips is most thankful.

BR JOhan

posted by Johan Svensson 27 Aug 2014

I2C communication is usually setup with a master and one or more slaves. All actions are initiated by the master. You can run the mbed as the master and implement slave code on the tiny. You need to design a robust protocol for the information exchange and then implement it. What are your needs.

posted by Wim Huiskamp 27 Aug 2014

Im doing a multi slave implimentation where the master is an mbed device with upto at least 30 slaves.

What I would need is a good ATtiny example with both read and write funtionality for both commands and to be able to set parameters internally ATtiny The ones I've found so far aren't that well commented or have no comment att all. I've tried to break it down and came up with a code that I thought would work. But as I'm not sure on the ways to send/receive i2c command/data I have problems on both sides. Also I need a working mbed example that work with the ATtiny setup in a correct way.

One other questen that I have is if I need a level converter between the mbed device and the ATtiny as the mbed device has 3.3V and the ATTiny has 5V.

Thankful to every little help I can get.

BR Johan

posted by Johan Svensson 28 Aug 2014

I havent worked with the ATTiny. I prefer to implement slaves like a RAM or EEPROM slave. That means the master sends the slaveaddress followed by a register/memory address to write to, followed by the data. The Slave remembers the address and autoincrements it after every interaction. Reading is done by first sending the slaveaddress and the register/memory address, then restarting the transaction by sending the slaveaddress with the readbit and then reading the required nr of bytes. Multiple slaves should all use different slaveaddresses. All traffic is initiated by the master. You have to define an addressmap for the slave and decide what functions are linked to a specific memory location in the slave.

I would recommend a levelconverter to improve reliability and robustness.

posted by Wim Huiskamp 28 Aug 2014