Advertisement
adunsmoor

Arduino I2C NCD Relay Control

Jun 28th, 2019
175
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.38 KB | None | 0 0
  1. #include <SPI.h>
  2. #include <Wire.h>
  3.  
  4. /***************************************************************************************** Configuration **************************************************************************************************/
  5.  
  6. // Board: Arduino/Genuino Uno
  7.  
  8. /***************** Links *****************/
  9. // Arduino Wire Library: https://www.arduino.cc/en/Reference/Wire
  10.  
  11. // NCD I2C Guide: https://ncd.io/i2c-communications-quick-start-guide/
  12. // 8 Channel NCD Relay Board: https://store.ncd.io/product/8-channel-high-power-relay-controller-with-i2c-interface/
  13. // 16 Channel NCD Relay Board: https://store.ncd.io/product/16-channel-high-power-relay-controller-with-i2c-interface/
  14. // 32 Channel NCD Relay Board: https://store.ncd.io/product/32-channel-high-power-relay-controller-with-i2c-interface/
  15.  
  16. // General
  17. const int baud_rate = 9600;
  18. const char *wire_errors[] = {
  19.     "",                                        // 0 (success)
  20.     "data too long to fit in transmit buffer", // 1
  21.     "received NACK on transmit of address ",   // 2
  22.     "received NACK on transmit of data ",      // 3
  23.     "other error"                              // 4
  24. };
  25.  
  26. // I2C Setup
  27. byte num_16_channel_boards = 2;                                            // 32 Channel Board counts as two 16 Channel Boards, (maximum = 8)
  28. const byte bus_addr[8] = {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27}; // these are the possible I2C addresses the relay boards support. The program assumes you are using sequential addresses.
  29. const byte bus_chan[2] = {0x12, 0x13};                                     // each group of 16 is made up of 2 groups of 8. Each group of 8 is communicated with individually. So a board of 32 will need 4 writes to it to set all 32 relays.
  30. const byte init_data[2] = {0x00, 0x01};                                    // each I2C address has to be initialized with this data. This is from the sample programs provided by NCD.io
  31.  
  32. // Relay Representation Map:
  33. // {0-7,  16-23, 32-39, 48-55, 64-71, 80-87, 96-103,  112-119}
  34. // {8-15, 24-31, 40-47, 56-63, 72-79, 88-95, 104-111, 120-127}
  35. byte relay_data[2][8] = {
  36.     {0, 0, 0, 0, 0, 0, 0, 0},
  37.     {0, 0, 0, 0, 0, 0, 0, 0}
  38. };
  39.  
  40. /***************************************************************************************** I2C Functions **************************************************************************************************/
  41.  
  42. // Configure the I2C bus addresses as output devices.
  43. void configure_I2C(byte numBanks)
  44. {
  45.   // loop through the 2 channels for each activated bank of relays. This nested loop configures the relays to be I2C outputs.
  46.   // the number of outer loops is based on the number of activated relay banks. The code won't try to write to relays that aren't connected.
  47.   for (byte i = 0; i < numBanks; i++)
  48.   {
  49.     for (byte j = 0; j < 2; j++)
  50.     {
  51.       Wire.beginTransmission(bus_addr[i]); // write I2C address
  52.       Wire.write(init_data[j]);            // write the initialization data for the channel (first channel is 0x00, second 0x01, this is from the sample program)
  53.       Wire.write(0x00);                    // always write 0x00 here. This is from the sample program.
  54.       byte ret = Wire.endTransmission();
  55.       if (ret)
  56.       {
  57.         Serial.print(F("Wire.endTransmission() >> ERROR = "));
  58.         Serial.println(wire_errors[ret]);
  59.       }
  60.       delay(10);
  61.     }
  62.   }
  63. }
  64.  
  65. // Write the contents of the I2C relay data matrix to the board with a nested loop.
  66. void write_I2C()
  67. {
  68.   for (byte i = 0; i < num_16_channel_boards; i++)
  69.   {
  70.     for (byte j = 0; j < 2; j++)
  71.     {
  72.       Wire.beginTransmission(bus_addr[i]);
  73.       Wire.write(bus_chan[j]);
  74.       Wire.write(relay_data[j][i]);
  75.       byte ret = Wire.endTransmission();
  76.       if (ret)
  77.       {
  78.         Serial.print(F("Wire.endTransmission() >> ERROR = "));
  79.         Serial.println(wire_errors[ret]);
  80.       }
  81.       delay(1);
  82.     }
  83.   }
  84. }
  85.  
  86. void write_to_relay(int group_16_num, int relay_num, int state)
  87. {
  88.   Wire.beginTransmission(bus_addr[group_16_num]);
  89.   if (relay_num < 9)
  90.   { // relays 1-8
  91.     Wire.write(bus_chan[0]);
  92.   }
  93.   else
  94.   { // relays 9-16
  95.     Wire.write(bus_chan[1]);
  96.   }
  97.   if (state)
  98.   {
  99.     Wire.write(relay_num);
  100.   }
  101.   else
  102.   {
  103.     Wire.write(relay_num);
  104.   }
  105.   byte ret = Wire.endTransmission();
  106.   if (ret)
  107.   {
  108.     Serial.print(F("Wire.endTransmission() >> ERROR = "));
  109.     Serial.println(wire_errors[ret]);
  110.   }
  111. }
  112.  
  113. // splits a 16 bit unsigned int into two 8 bit sections. The 8 bit sections are 16 bits still, but the last 8 bits will be 0.
  114. void set_relay_data(unsigned int bus_data, int bus_num)
  115. {
  116.   //        [y][x]
  117.   relay_data[0][bus_num] = (bus_data)&0xff;
  118.   relay_data[1][bus_num] = (bus_data / 256) & 0xff;
  119. }
  120.  
  121. /***************************************************************************************** Arduino Functions **************************************************************************************************/
  122.  
  123. void loop()
  124. {
  125.   set_relay_data(1158, i);
  126.   write_I2C();
  127.   delay(10);
  128. }
  129.  
  130. void setup()
  131. {
  132.   // Open serial communications and wait for port to open:
  133.   Serial.begin(baud_rate);
  134.   while (!Serial)
  135.   {
  136.     ; // wait for serial port to connect. Needed for native USB port only
  137.   }
  138.  
  139.   // I2C setup
  140.   Wire.begin();
  141.   configure_I2C(num_16_channel_boards); // initialize relay boards as an output device
  142.   write_I2C();                          // reset relays on boot
  143.  
  144.   Serial.println(F("setup finished"));
  145. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement