Hi Guys, im having trouble with getting my Arduino to actually communicate over the i2c bus to toggle relay outputs.
This is the code i currently have,
Relay Controller MQTT Code
#include <SPI.h>
#include “Ethernet.h”
#include “Wire.h”
#include <PubSubClient.h>
#include <stdlib.h>
#define SHIELD_1_I2C_ADDRESS 0x20 // 0x20 is the address with all jumpers removed
#define SHIELD_2_I2C_ADDRESS 0x21 // 0x21 is the address with a jumper on position A0
#define MAC_I2C_ADDRESS 0x50 // Microchip 24AA125E48 I2C ROM address
/* If channelInterlocks is set to true, the channels are grouped into
- pairs starting at 1 (ie: channels 1 & 2, 3 & 4, etc) and only one
- channel in each pair can be on at any time. For example, if channel
- 1 is on and 2 is set to on, channel 1 will be turned off first and
- vice versa. This is to allow control of dual-active devices such as
- electric curtain motors which must only be driven in one direction
- at a time. */
const byte channelInterlocks = false;
/* CHANGE THIS TO YOUR OWN UNIQUE VALUE. The MAC number should be
- different from any other devices on your network or you’ll have
- problems receiving packets. Can be replaced automatically below
- using a MAC address ROM. */
static uint8_t mac[] = { 0xDE, 0xA7, 0x0E, 0xEF, 0xFE, 0xED };
/* CHANGE THIS TO MATCH YOUR HOST NETWORK. Most home networks are in
- the 192.168.0.XXX or 192.168.1.XXX subrange. Pick an address
- that’s not in use and isn’t going to be automatically allocated by
- DHCP from your router. Can be replaced automatically using DHCP. */
static uint8_t ip[] = { 192, 168, 1, 182 };
static uint8_t serverIP[] = { 192, 168, 1, 108 };
char* outputTopic="/output";
char topic[37];
char message[22];
byte shield1BankA = 0; // Current status of all outputs on first shield, one bit per output
byte shield2BankA = 0; // Current status of all outputs on second shield, one bit per output
EthernetClient ethClient;
PubSubClient client(serverIP, 1883, ethClient);
// New message receive
void callback(char* topic, byte* payload, unsigned int length) {
String strPayload= String((char*)payload).substring(0,length);
Serial.print(“Receive message”);
Serial.println(strPayload);
// topic will be something like /relay/power/1/01
char channel[]=" ";
channel[0]= *(topic+13);
channel[1]= *(topic+14);
unsigned short int relay = atoi(channel);
if (strPayload.equals(“on”))
{
setLatchChannelOn( relay );
publishState(atoi(channel),1,outputTopic);
Serial.print("Turning on ");
Serial.println(channel);
}
if (strPayload.equals("off"))
{
setLatchChannelOff( relay );
publishState(atoi(channel),0,outputTopic);
Serial.print("Turning off ");
Serial.println(channel);
}
}
void setup()
{
Wire.begin(); // Wake up I2C bus
Serial.begin( 38400 );
Serial.println(“Strting MQTT Relay 8 board”);
Serial.print("Getting MAC address from ROM: ");
// mac[0] = readRegister(0xFA);
// mac[1] = readRegister(0xFB);
// mac[2] = readRegister(0xFC);
// mac[3] = readRegister(0xFD);
// mac[4] = readRegister(0xFE);
// mac[5] = readRegister(0xFF);
char tmpBuf[17];
sprintf(tmpBuf, “%02X:%02X:%02X:%02X:%02X:%02X”, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
Serial.println(tmpBuf);
// setup the Ethernet library to talk to the Wiznet board
Ethernet.begin(mac, ip); // Use static address defined above
//Ethernet.begin(mac); // Use DHCP
// Print IP address:
Serial.print(“My IP: “);
for (byte thisByte = 0; thisByte < 4; thisByte++) {
// print the value of each byte of the IP address:
Serial.print(Ethernet.localIP()[thisByte], DEC);
if( thisByte < 3 )
{
Serial.print(”.”);
}
}
/* Set up the Relay8 shields */
initialiseShield(SHIELD_1_I2C_ADDRESS);
sendRawValueToLatch1(0); // If we don’t do this, channel 6 turns on! I don’t know why
initialiseShield(SHIELD_2_I2C_ADDRESS);
sendRawValueToLatch2(0); // If we don’t do this, channel 6 turns on! I don’t know why
Serial.println(“Ready.”);
}
void connect() {
if (client.connect(“arduinoClient”, “openhabian”, “bedrock”)) {
Serial.println(“Connected”);
client.subscribe("/relay/power/1/#");
}
}
void loop()
{
if (!client.connected()) {
connect();
}
client.loop();
}
void publishState(int channel,int state,char* theTopic) {
sprintf(topic,theTopic,channel);
sprintf(message,"{channel:%1d,state:%1d}",channel,state);
client.publish(topic,message);
}
void initialiseShield(int shieldAddress)
{
// Set addressing style
Wire.beginTransmission(shieldAddress);
Wire.write(0x12);
Wire.write(0x20); // use table 1.4 addressing
Wire.endTransmission();
// Set I/O bank A to outputs
Wire.beginTransmission(shieldAddress);
Wire.write(0x00); // IODIRA register
Wire.write(0x00); // Set all of bank A to outputs
Wire.endTransmission();
}
/**
*/
void toggleLatchChannel(byte channelId)
{
if( channelId >= 1 && channelId <= 8 )
{
byte shieldOutput = channelId;
byte channelMask = 1 << (shieldOutput - 1);
shield1BankA = shield1BankA ^ channelMask;
sendRawValueToLatch1(shield1BankA);
}
else if( channelId >= 9 && channelId <= 16 )
{
byte shieldOutput = channelId - 8;
byte channelMask = 1 << (shieldOutput - 1);
shield2BankA = shield2BankA ^ channelMask;
sendRawValueToLatch2(shield2BankA);
}
}
/**
*/
void setLatchChannelOn (byte channelId)
{
if( channelInterlocks == true )
{
if ( (channelId % 2) == 0) // This is an even number channel, so turn off the channel before it
{
setLatchChannelOff( channelId - 1 );
} else { // This is an odd number channel, so turn off the channel after it
setLatchChannelOff( channelId + 1 );
}
}
if( channelId >= 1 && channelId <= 8 )
{
byte shieldOutput = channelId;
byte channelMask = 1 << (shieldOutput - 1);
shield1BankA = shield1BankA | channelMask;
sendRawValueToLatch1(shield1BankA);
}
else if( channelId >= 9 && channelId <= 16 )
{
byte shieldOutput = channelId - 8;
byte channelMask = 1 << (shieldOutput - 1);
shield2BankA = shield2BankA | channelMask;
sendRawValueToLatch2(shield2BankA);
}
}
/**
*/
void setLatchChannelOff (byte channelId)
{
if( channelId >= 1 && channelId <= 8 )
{
byte shieldOutput = channelId;
byte channelMask = 255 - ( 1 << (shieldOutput - 1));
shield1BankA = shield1BankA & channelMask;
sendRawValueToLatch1(shield1BankA);
}
else if( channelId >= 9 && channelId <= 16 )
{
byte shieldOutput = channelId - 8;
byte channelMask = 255 - ( 1 << (shieldOutput - 1));
shield2BankA = shield2BankA & channelMask;
sendRawValueToLatch2(shield2BankA);
}
}
/**
*/
void sendRawValueToLatch1(byte rawValue)
{
Wire.beginTransmission(SHIELD_1_I2C_ADDRESS);
Wire.write(0x12); // Select GPIOA
Wire.write(rawValue); // Send value to bank A
shield1BankA = rawValue;
Wire.endTransmission();
}
/**
*/
void sendRawValueToLatch2(byte rawValue)
{
Wire.beginTransmission(SHIELD_2_I2C_ADDRESS);
Wire.write(0x12); // Select GPIOA
Wire.write(rawValue); // Send value to bank A
shield2BankA = rawValue;
Wire.endTransmission();
}
/**
- Required to read the MAC address ROM
*/
byte readRegister(byte r)
{
unsigned char v;
Wire.beginTransmission(MAC_I2C_ADDRESS);
Wire.write®; // Register to read
Wire.endTransmission();
Wire.requestFrom(MAC_I2C_ADDRESS, 1); // Read a byte
while(!Wire.available())
{
// Wait
}
v = Wire.read();
return v;
}
not all of it is mine so im trying to piece this together. i should be able to publish into /relay/power/1/01
‘on’ or ‘off’ and that should trigger the relay. am i missing something here?
@chris something you could possibly help me with?
Thanks again for your help