IOT123 - I2C HEARTBEAT BRICK

About: The tension between novelty and familiarity...

The IOT123 BRICKS are DIY modular units that can be mashed up with other IOT123 BRICKS, to add functionality to a node or wearable. They are based on the inch square, double-sided protoboards with interconnected through holes.

A number of these BRICKS are expected to be on multiple nodes (Master MCUs - ESP8266 or ATTINY84) on a site. The MCU needs no prior knowledge of the sensors purpose or software needs. It scans for I2C nodes then requests a property dump (sensor data) from each slave. These BRICKs supply 5.0V, 3.3V and another AUX line which is customizable.

This I2C HEARTBEAT BRICK indicates whether the ATTINY slave is alive, also the I2C traffic, and has one property:

STATUS ("ALIVE")

PB1 (white) indicates ATTINY health.

PB3 (yellow) toggles with I2C requests from the master.

PB4 (orange) toggles with I2C receiving from the master.

The through-holes adjacent to the ATTINY85 have been left unused, to enable a pogo pin programmer while the DIP8 is soldered to the PCB. A further abstraction, packaging the BRICKS in small cylinders that plug into a D1M WIFI BLOCK hub, pumping the values to a MQTT server, is being developed.

Step 1: Materials and Tools

    There is a full Bill of Material and Sourcing list.

    1. Paper PCB (7 x 7 holes)
    2. LEDS (Red, Green, Blue)
    3. Resistors (3 off 1K)
    4. ATTINY85 20PU (1)
    5. 1" Double sided protoboard (1)
    6. Male Header 90º (3P, 3P)
    7. Male Header (2P, 2P)
    8. Jumper Shunt (1)
    9. Hookup wire (~7)
    10. Solder and Iron (1)

    Step 2: Prepare the ATTINY85

    NOTE: If intending to have Crouton integration, please use the library from here, and use the example installed "attiny_heartbeat"

    AttinyCore from the Boards Manager is needed. Burn bootloader "EEPROM Retained", "8mHZ Internal" (all config shown above).

    The code repository can be found here.

    A ZIP of the library can be found here.

    Instructions for "Importing a ZIP Library" here.

    Once the library is installed you can open the example "attiny_heartbeat".

    To upload the firmware to the ATTINY85, you may find more details in these instructables:

    https://www.instructables.com/id/Programming-the-....

    https://www.instructables.com/id/How-to-Program-A...

    https://www.instructables.com/id/Programming-the-...

    https://www.instructables.com/id/How-to-Program-A...

    https://www.instructables.com/id/Programming-the-...

    Best to test via breadboard before continuing.

    If you have existing ASSIMILATE SENSORS, make sure the slave address is different on a SENSOR/MCU Host combination e.g. all the Relay actors can have the same address as long as you only have one Relay actor on a MCU/node.

    Step 3: Assembling the Indicators

    The indicators are meant to be fully customizable. It is the event signals from the main circuit that are seen as Heartbeats. For this build we will use LED indicators; your build can use relays (yes the VCC is broken out) or another visual/signal based indicator. The resistor values will depend on personal preference on how bright you want them.

    1. On the top, insert a blue LED into RED1 (+) and BLACK1 (G), and solder on bottom.
    2. On the bottom, bend the lead from RED1 so it touches the copper pad on SILVER8 and trim.
    3. On the bottom, trim lead from BLACK1 above solder.
    4. On the top, insert a green LED into RED2 (+) and BLACK2 (G), and solder on bottom.
    5. On the bottom, bend the lead from RED2 so it touches the copper pad on SILVER9 and trim.
    6. On the bottom, trim lead from BLACK2 above solder.
    7. On the top, insert a red LED into RED3 (+) and BLACK3 (G), and solder on bottom.
    8. On the bottom, bend the lead from RED3 so it touches the copper pad on SILVER10 and trim.
    9. On the bottom, trim lead from BLACK3 above solder.
    10. On the top, insert a 1K resistor into through-holes SILVER1 and SILVER4.
    11. On the bottom, trace, trim and solder lead from SILVER1 onto BLACK1.
    12. On the top, insert a 1K resistor into through-holes SILVER2 and SILVER4.
    13. On the bottom, trace, trim and solder lead from SILVER2 onto BLACK2.
    14. On the top, insert a 1K resistor into through-holes SILVER3 and SILVER4.
    15. On the bottom, trace, trim and solder lead from SILVER3 onto BLACK3.
    16. On the bottom, solder wires on SILVER4 and trim at about 5mm extending.
    17. On the bottom, solder a black wire onto SILVER4.
    18. On the bottom, solder a white wire into SILVER5, ensuring continuity to lead from RED1.
    19. On the bottom, solder a yellow wire into SILVER6, ensuring continuity to lead from RED2.
    20. On the bottom, solder a orange wire into SILVER7, ensuring continuity to lead from RED3.

    Step 4: Assembling the Main Circuit

    Assembly:

    1. On the front, insert the components ATTINY85 (1), 3P 90deg male headers (2)(3), 3P male headers (4)(5) and solder off on the rear.
    2. On the rear, trace a yellow wire from YELLOW1 to YELLOW2 and solder.
    3. On the rear, trace a orange wire from ORANGE1 to ORANGE2 and solder.
    4. On the rear, trace a blue wire from BLUE1 to BLUE2 and solder.
    5. On the rear, trace a green wire from GREEN1 to GREEN2 and solder.
    6. On the rear, trace a white wire from WHITE1 to WHITE2 and solder.
    7. On the rear, trace a black wire from BLACK1 to BLACK2 and solder.
    8. On the rear, trace a black wire from BLACK3 to BLACK4 and solder.
    9. On the rear, trace a red wire from RED1 to RED2 and solder.
    10. On the rear, trace a bare wire from RED3 to RED4 and solder.
    11. On the rear, trace a bare wire from SILVER1 to SILVER2 and solder.
    12. Add a jumper on the 5V or 3V3 line.

    If using the Indicators above (refer to pinout diagram):

    1. On the rear, solder the white wire into PB1.
    2. On the rear, solder the yellow wire into PB3.
    3. On the rear, solder the orange wire into PB4.
    4. On the rear, solder the black wire into GND.

    Step 5: Testing

    A number of these BRICKS are expected to be on multiple nodes (MCUs - ESP8266 or ATTINY84) in an environment. This is a unit test: sends I2C commands from the UNO to the ATTINY which toggles the Receive LED. The ATTINY ALIVE LED stays on.

    We have previously built a I2C SHIELD for Arduino.


    If you want to breadboard it instead:

    1. Connect the 5.0V on UNO to a VCC on BRICK.
    2. Connect the GND on UNO to GND on BRICK.
    3. Connect the A5 on UNO to SCL on BRICK.
    4. Connect the A4 on UNO to SDA on BRICK.
    5. Connect a 4K7 pull-up resistor from SDA to VCC.
    6. Connect a 4K7 pull-up resistor from SCL to VCC.

    Running the test.

    1. Connect your UNO to your Dev PC with USB.
    2. Upload the code to the UNO.
    3. Open the Arduino Console.
    4. Choose 9600 baud (restart the UNO and reopen the console if you have to).
    5. The address of the slave will print to the console.
    6. When <Arduino is ready>, enter in the send box <ADDRESS> 2 1 (so 16 2 1), and the Receive LED turns on.
    7. When <Arduino is ready>, enter in the send box <ADDRESS> 2 0 (so 16 2 0), and the Receive LED turns off.

    I2C BRICK adhoc commands for slaves from UNO master.

    #include<Wire.h>
    const byte _num_chars = 32;
    char _received_chars[_num_chars]; // an array to store the received data
    boolean _has_new_data = false;
    voidsetup() {
    Serial.begin(9600);
    Serial.println();
    Serial.println("ASSIMILATE IOT ACTOR/SENSOR EEPROM EDITOR");
    Serial.println("ensure newline selected in console window");
    Serial.println();
    Serial.println("ADDRESS 1 CONFIRM METADATA RECEIPT N/A (FOR M2M)");
    Serial.println("ADDRESS 2 ACTOR COMMAND");
    Serial.println();
    Serial.println("ADDRESSES ON BUS:");
    scan_i2c_addresses();
    Serial.println();
    Serial.println("");
    }
    voidscan_i2c_addresses(){
    int device_count = 0;
    for (byte address = 8; address < 127; address++)
    {
    Wire.beginTransmission(address);
    const byte error = Wire.endTransmission();
    if (error == 0)
    {
    Serial.println(address);
    }
    }
    }
    voidloop() {
    recv_with_end_marker();
    send_to_i2c();
    }
    voidrecv_with_end_marker() {
    static byte ndx = 0;
    char end_marker = '\n';
    char rc;
    while (Serial.available() >0 && _has_new_data == false) {
    rc = Serial.read();
    if (rc != end_marker) {
    _received_chars[ndx] = rc;
    ndx++;
    if (ndx >= _num_chars) {
    ndx = _num_chars - 1;
    }
    }
    else {
    _received_chars[ndx] = '\0'; // terminate the string
    ndx = 0;
    _has_new_data = true;
    }
    }
    }
    voidsend_to_i2c() {
    char param_buf[16];
    const String received_string = String(_received_chars);
    if (_has_new_data == true) {
    int idx1 = received_string.indexOf('');
    String address = received_string.substring(0, idx1);
    int address_int = address.toInt();
    if (address_int < 8 || address_int >127){
    Serial.println("INVALID ADDRESS INPUT:");
    Serial.println(address);
    return;
    }
    int idx2 = received_string.indexOf('', idx1+1);
    String code;
    if (idx2 == -1){
    code = received_string.substring(idx1+1);
    }else{
    code = received_string.substring(idx1+1, idx2+1);
    }
    int code_int = code.toInt();
    if (code_int < 0 || code_int >5){
    Serial.println("INVALID CODE INPUT:");
    Serial.println(code);
    return;
    }
    bool has_parameter = idx2 > -1;
    String parameter;
    if (has_parameter){
    parameter = received_string.substring(idx2 + 1, idx2 + 17); // 16 chars max
    if (parameter.length() < 1){
    Serial.println("PARTAMETER MIN. LENGTH 1");
    _has_new_data = false;
    return;
    }
    }else{
    if (code_int >1){
    Serial.println("PARAMETER REQUIRED!");
    _has_new_data = false;
    return;
    }
    }
    Serial.println();
    Serial.print("input orig = ");
    Serial.println(received_string);
    Serial.print("address = ");
    Serial.println(address);
    Serial.print("code = ");
    Serial.println(code);
    Serial.print("parameter = ");
    Serial.println(parameter);
    // SEND VIA I2C
    Wire.beginTransmission(address_int);
    Wire.write(code_int);
    if (has_parameter){
    parameter.trim();
    strcpy(param_buf, parameter.c_str());
    Wire.write(param_buf);
    }
    Wire.endTransmission();
    Serial.println();
    Serial.println("SENT VIA I2C!");
    Serial.println();
    Serial.println("");
    _has_new_data = false;
    }
    }

    Step 6: Next Steps

    The follow-up ASSIMILATE ACTOR: HEARTBEAT which uses this brick has automatic configuration for Crouton via the metadata already installed in the ATTINY85 here. The JSON packet sent to Crouton is sent via the latest firmware for the ICOS10. You can do a Proof-of-concept on an ordinary ESP8266, if the build is a too much for now.

    The UNO sketch used in Testing has a function for saving a new slave address to EEPROM on the ATTINY85, if you have a clash on your target I2C bus.

    Check out the ASSIMILATE SENSORS and IOT123 BRICKS.

    Share

      Recommendations

      • Big and Small Contest

        Big and Small Contest
      • First Time Author

        First Time Author
      • PCB Contest

        PCB Contest

      Discussions