collapse

Welcome!



Welcome to Robot Rebels, an online robot maker community.

Register today to post your projects, ask questions, share knowledge and meet like-minded people from around the world.


The RobotRebel.org Community

Author Topic: Coding a Nano i2c Slave  (Read 258 times)

BaldwinK

  • Member
  • ****
  • B
  • Posts: 13
Coding a Nano i2c Slave
« on: October 25, 2017, 05:40:27 AM »
In a distributed system using intelligent leg modules and a central controller, each 4-motor leg module could be addressed as an i2c slave. The Nano is reasonably compact, has 18 usable I/O pins and is very cheap.

For earlier projects I used various PICAXE chips but needed higher mathematical capability.  Transitioning to the Arduino IDE I wrote master i2c bit banging code for a Nano as a learning exercise. It worked well enough to interface to IMU chips etc and to teach me to watch out for semicolons and double equals.

Of course the slave chips use hardware to detect fast edges and it is quite difficult to use software loops for the same effect. I had also missed the chapter on i2c in the Atmel datasheet because it is headed TWI.

It turns out writing code for an i2c slave is a lot easier using the Atmel registers.

Using the Hardware

First load the slave address (hex 50 say):

    TWAR = 0x50;                 //slave address to Atmel

Then turn on the hardware i2c function using the control register:

    TWCR = B01000100;            //set TWEA, enable Atmel i2c
    TWCR = TWCR | B10000000;     //hit the flag to get it going

Now wait for the status register to see what has occurred:

    while (!(TWCR & B10000000)); //wait flag to read status

Let’s assume the master is going to write (send data to us):

    if (TWSR == 0x60) {          //test status for addr + W found
                                 //the address found is in the data register

We hit the flag and wait for the first data byte:

    TWCR = TWCR | B10000000;     //hit the flag
    while (!(TWCR & B10000000)); //wait flag

    if (TWSR != 0x80)            //test status for data received ok
    goto error_handler;

    inbyte = TWDR;               //the first byte is in the data register
    }

Continue as required. Obviously things are a little more complicated but the detail can be added once you get the idea. The Atmel datasheet is a must read and pay special attention to the protocol of Nacking the last byte.

Trimming the Protocol

My quadruped project has specific needs so the i2c protocol can be tailored to suit the need for speed etc.

Each of the four motors needs byte values for:

    Actual position in degrees  (read only)
    Next setpoint in degrees    (read/write)
    Current duty cycle 0 to 255 (read only)
    Maximum duty cycle 0 to 255 (read/write)

Driving the motors at twice normal voltage is good for torque but if a 50% duty cycle is exceeded for too long the motors or drivers will cook. This calculation needs a 64-byte fifo for a one second moving average of the PWM value. The motor power is removed for each period the maximum value is exceeded. It sounds like braking on gravel in a car fitted with an ABS system.

All data transfers will be four bytes long. Makes the thinking simpler.

The four parameters will not use a separate register address byte; the extra two bits can be a subset of the leg address.

Atmel got there first with the TWAMR bit-masking of the TWAR:

    TWAMR = 0x0C;                //mask out lower bits (Reg address)

So there is no switching from writing the register address, sending a restart, then reading the data bytes.  Whether reading or writing, transfers can be completed in less than 150uS.

Synchronising the Processes

Each slave Nano has to calculate four PID equations compensating for non-linear potentiometers, update duty cycle values, scale for each PWM and control the half bridges. This may take 12-13mS of the 15mS cycle time.  Keeping the cycle-time constant simplifies the calculus because the .dt elements can be removed.

Once its housekeeping is done, the slave will be ready to listen to the i2c bus. The master can then send or receive i2c instructions to each slave before the cycle restarts.

Neither process is interrupted but we do need to keep them meshing together.

The Atmel hardware can be configured for a ‘general call’ address 0x00.  The LSB of the TWAR register is set to enable the slave to respond to its own address and the general call address:

    TWAR = i2cadd | 0x01;        //slave address to Atmel, allow general call

Once the address is seen the slaves will start their own processes and will not listen to the i2c bus for a while:

    if (TWSR == 0x70)            //test status for general call
    goto house_keeping

The master is also free for a time to do its own thing.  Then when millis() counts out 13mS it must converse on the i2c bus. At 15mS it must send the general call address, finishing with a stop bit to keep everyone happy.

 

* Search


* Recent Topics

Welcome to the model section by jinx
[January 20, 2018, 10:11:40 AM]


syncthing - true p2p directory sync by mogul
[January 18, 2018, 03:21:49 PM]


Youtube by Impala
[January 18, 2018, 01:36:26 PM]


Bob's gone Wood by Protowrxs
[January 16, 2018, 10:41:57 PM]


Automatic Garage Door malfunction by Protowrxs
[January 16, 2018, 05:34:00 PM]


speech synthesizer chip by Protowrxs
[January 16, 2018, 05:22:22 PM]


Spider by Protowrxs
[January 16, 2018, 05:18:26 PM]


CZ-1 2.0: problems, calibration and printing, part2 by MEgg
[January 14, 2018, 06:35:28 PM]


3D printing: autoleveling, autoadjustment by MEgg
[January 09, 2018, 05:18:46 PM]


Simple One-Servo Walker by ZeroMax
[January 03, 2018, 10:04:07 PM]


Anycubic Kossel (pulley) by Deity
[December 31, 2017, 09:04:23 AM]


Merry Christmas by Impala
[December 24, 2017, 12:04:45 AM]


printed CNC engraver by jinx
[December 17, 2017, 04:45:43 AM]


metal chassis desktop bot by craighissett
[December 14, 2017, 06:55:16 AM]


LEGO by Impala
[December 13, 2017, 09:46:53 PM]

* Recent Posts

Welcome to the model section by jinx
[January 20, 2018, 10:11:40 AM]


syncthing - true p2p directory sync by mogul
[January 18, 2018, 03:21:49 PM]


Re: Youtube by Impala
[January 18, 2018, 01:36:26 PM]


Re: Youtube by mogul
[January 18, 2018, 04:36:47 AM]


Re: Youtube by jinx
[January 18, 2018, 03:04:42 AM]


Youtube by Impala
[January 17, 2018, 10:23:59 AM]


Re: Bob's gone Wood by Protowrxs
[January 16, 2018, 10:41:57 PM]


Bob's gone Wood by ZeroMax
[January 16, 2018, 06:49:12 PM]


Re: Automatic Garage Door malfunction by Protowrxs
[January 16, 2018, 05:34:00 PM]


Re: speech synthesizer chip by Protowrxs
[January 16, 2018, 05:22:22 PM]


Re: Spider by Protowrxs
[January 16, 2018, 05:18:26 PM]


Spider by viswesh
[January 15, 2018, 01:14:19 PM]


Re: CZ-1 2.0: problems, calibration and printing, part2 by MEgg
[January 14, 2018, 06:35:28 PM]


Re: speech synthesizer chip by ZeroMax
[January 14, 2018, 01:49:46 PM]


Re: CZ-1 2.0: problems, calibration and printing, part2 by MEgg
[January 14, 2018, 01:09:24 PM]