Hi there, this is my first question in hass forum. recent days I made a 4-channel-dimmer with the sketch of MYsensors 4-channel-dimmer
As a newbie, and with my poor English ability, I finished the hardware job. But with the oringinal ino code, I can’t use it in HA. I only had the switches showing as the pictures below. I can saw the switch, the dimmer do not showing.
With the MYSController, I can set the dimmer smoothly
The oringinal ino code is here(use mysensors protocol 1.5), and I used a mysensors esp8266-wifi-gateway with the mysensors-protocol 2.1.1
#include <SPI.h>
#include <EEPROM.h>
#include "MySensor.h"
// Enable debug prints to serial monitor
#define MY_DEBUG
// Enable and select radio type attached
#define MY_RADIO_NRF24
#define RF24_CHANNEL 76
#define MY_NODE_ID 18
#define LEVEL_ON 1
#define LEVEL_OFF 0
#define RESOLUTION 65536 // Timer1 is 16 bit
#define MICROSECONDS 96 // Interrupt interval
#define NUM_SWITCHES 8
#define NUM_CHANNELS 4
#define SWITCH_1_ID 1
#define SWITCH_2_ID 2
#define SWITCH_3_ID 3
#define SWITCH_4_ID 4
#define SWITCH_5_ID 5
#define SWITCH_6_ID 6
#define SWITCH_7_ID 7
#define SWITCH_8_ID 8
#define CHANNEL_1_ID 11
#define CHANNEL_2_ID 12
#define CHANNEL_3_ID 13
#define CHANNEL_4_ID 14
#define DIMMER_1_ID 21
#define DIMMER_2_ID 22
#define DIMMER_3_ID 23
#define DIMMER_4_ID 24
#define ALLOW_BRIGHT_1_ID 31
#define ALLOW_BRIGHT_2_ID 32
#define ALLOW_BRIGHT_3_ID 33
#define ALLOW_BRIGHT_4_ID 34
#define CHANNEL_1_ADDR EEPROM_LOCAL_CONFIG_ADDRESS + 1
#define CHANNEL_2_ADDR CHANNEL_1_ADDR + 1
#define CHANNEL_3_ADDR CHANNEL_2_ADDR + 1
#define CHANNEL_4_ADDR CHANNEL_3_ADDR + 1
#define DIMMER_1_ADDR CHANNEL_4_ADDR + 1
#define DIMMER_2_ADDR DIMMER_1_ADDR + 1
#define DIMMER_3_ADDR DIMMER_2_ADDR + 1
#define DIMMER_4_ADDR DIMMER_3_ADDR + 1
#define ALLOW_BRIGHT_1_ADDR DIMMER_4_ADDR + 1
#define ALLOW_BRIGHT_2_ADDR ALLOW_BRIGHT_1_ADDR + 1
#define ALLOW_BRIGHT_3_ADDR ALLOW_BRIGHT_2_ADDR + 1
#define ALLOW_BRIGHT_4_ADDR ALLOW_BRIGHT_3_ADDR + 1
MySensor gw;
MyMessage msg(0, V_STATUS);
volatile byte FULL_BRIGHT=100;
volatile byte LOW_BRIGHT=20;
volatile byte PIN_IN[] = {3,4,5,6,7,8,A6,A7};
volatile byte PIN_OUT[] = {17,16,15,14};
volatile byte chState[] = {0,0,0,0};
volatile byte chDimmer[] = {0,0,0,0};
byte allowBright[] = {1,1,1,1};
byte curSwitch[] = {0,0,0,0,0,0,0,0};
byte oldSwitch[] = {0,0,0,0,0,0,0,0};
unsigned long offTime[] = {0,0,0,0};
volatile byte maxPWM[] = {FULL_BRIGHT,FULL_BRIGHT,FULL_BRIGHT,FULL_BRIGHT};
volatile int Tick = 0;
void setup() {
// mySensors init //
gw.begin(incomingMessage, MY_NODE_ID);
// Send the sketch version information to the gateway and Controller
gw.sendSketchInfo("Dimmer", "1.00");
// Register all sensors
presentation();
delay(500);
// restore values from EEPROM
if (EEPROM.read(CHANNEL_1_ADDR) == 255){
configReset();
}
for (byte i=0; i<NUM_CHANNELS; i++) {
chState[i] = EEPROM.read(CHANNEL_1_ADDR+i);
}
for (byte i=0; i<NUM_CHANNELS; i++) {
maxPWM[i] = EEPROM.read(DIMMER_1_ADDR+i);
}
for (byte i=0; i<NUM_CHANNELS; i++) {
allowBright[i] = EEPROM.read(ALLOW_BRIGHT_1_ADDR+i);
}
// pins mode setup
for (byte i=0; i<NUM_SWITCHES; i++) {
pinMode(PIN_IN[i], INPUT);
oldSwitch[i] = curSwitch[i] = digitalRead(PIN_IN[i]);
}
for (byte i=0; i<NUM_CHANNELS; i++) {
pinMode(PIN_OUT[i], OUTPUT);
gw.send(msg.setSensor(i+11).set(chState[i]));
delay(100);
}
for (byte i=0; i<NUM_CHANNELS; i++) {
gw.send(msg.setSensor(i+21).set(maxPWM[i]));
delay(100);
}
// Timer1 interrupt setup
TimerOneInitialize(MICROSECONDS); // set a timer period
TIMSK1 &= ~_BV(TOIE1); // clears the timer overflow interrupt enable bit
// clocking from AC~220
pinMode(2, INPUT);
digitalWrite(2, HIGH);
attachInterrupt(0, zero_cross, RISING);
}
// the loop function runs over and over again forever
void loop() {
gw.process();
for (byte i=0; i<NUM_CHANNELS; i++) {
curSwitch[i] = digitalRead(PIN_IN[i]);
if (oldSwitch[i] != curSwitch[i]) { // check state of switch is changed
if (curSwitch[i] == HIGH) { // switch ON
if ( ((millis()-offTime[i]) >100) || ((millis()-offTime[i]) <1000) && (allowBright[i] > 0) ) { // set or unset night mode
if (maxPWM[i] == FULL_BRIGHT) {
maxPWM[i] = LOW_BRIGHT;
} else {
maxPWM[i] = FULL_BRIGHT;
}
gw.send(msg.setSensor(i+21).set(maxPWM[i]));
EEPROM.write(DIMMER_1_ADDR+i, maxPWM[i]);
}
chState[i] = 1;
} else { // switch OFF
chState[i] = 0;
offTime[i] = millis();
}
oldSwitch[i] = curSwitch[i];
gw.send(msg.setSensor(i+11).set(chState[i]));
EEPROM.write(CHANNEL_1_ADDR+i, chState[i]);
}
}
for (byte i=NUM_CHANNELS; i<NUM_SWITCHES-2; i++) {
curSwitch[i] = digitalRead(PIN_IN[i]);
if (oldSwitch[i] != curSwitch[i]) {
gw.send(msg.setSensor(i+1).set(curSwitch[i]));
oldSwitch[i] = curSwitch[i];
}
}
}
void TimerOneInitialize(long microseconds)
{
TCCR1A = 0; // clear control register A
TCCR1B = _BV(WGM13); // set mode 8: phase and frequency correct pwm, stop the timer
TimerOneSetPeriod(microseconds);
}
void TimerOneSetPeriod(long microseconds)
{
unsigned int pwmPeriod;
unsigned char clockSelectBits;
char oldSREG; // To hold Status Register while ints disabled
long cycles = (F_CPU / 2000000) * microseconds; // the counter runs backwards after TOP, interrupt is at BOTTOM so divide microseconds by 2
if(cycles < RESOLUTION) clockSelectBits = _BV(CS10); // no prescale, full xtal
else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11); // prescale by /8
else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11) | _BV(CS10); // prescale by /64
else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12); // prescale by /256
else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12) | _BV(CS10); // prescale by /1024
else cycles = RESOLUTION - 1, clockSelectBits = _BV(CS12) | _BV(CS10); // request was out of bounds, set as maximum
oldSREG = SREG;
cli(); // Disable interrupts for 16 bit register access
ICR1 = pwmPeriod = cycles; // ICR1 is TOP in p & f correct pwm mode
SREG = oldSREG;
TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12));
TCCR1B |= clockSelectBits; // reset clock select register, and starts the clock
}
ISR(TIMER1_OVF_vect) // interrupt service routine
{
if ( Tick > 0) {
// channel ON if need
for (byte i=0; i<NUM_CHANNELS; i++) {
if ( Tick == chDimmer[i] ) {
digitalWrite(PIN_OUT[i], LEVEL_ON);
}
}
} else {
TIMSK1 &= ~_BV(TOIE1); // clears the timer overflow interrupt enable bit
// all channels OFF
for (byte i=0; i<NUM_CHANNELS; i++) {
if ((chState[i]>0) && (maxPWM[i]==255)) {
} else {
digitalWrite(PIN_OUT[i], LEVEL_OFF);
}
}
}
Tick--;
}
void zero_cross() {
//
TIMSK1 &= ~_BV(TOIE1); // clears the timer overflow interrupt enable bit
// all channels OFF
for (byte i=0; i<NUM_CHANNELS; i++) {
if ((chState[i]>0) && (maxPWM[i]==255)) {
} else {
digitalWrite(PIN_OUT[i], LEVEL_OFF);
}
}
//
// inc/dec dimmer value (bright)
for (byte i=0; i<NUM_CHANNELS; i++) {
if (maxPWM[i] > FULL_BRIGHT) {
if ( chState[i] > 0 ) {
chDimmer[i] = FULL_BRIGHT;
} else {
chDimmer[i] = 0;
}
} else {
if ( chState[i] > 0 ) {
if ( chDimmer[i] < maxPWM[i] ) chDimmer[i]++;
if ( chDimmer[i] > maxPWM[i] ) chDimmer[i]--;
} else {
if ( chDimmer[i] > 0 ) chDimmer[i]--;
}
}
}
// start countdown
Tick = FULL_BRIGHT;
TIMSK1 = _BV(TOIE1); // sets the timer overflow interrupt enable bit
}
void presentation() {
/* gw.present(SWITCH_1_ID, V_STATUS, "Switch1");
delay(100);
gw.present(SWITCH_2_ID, V_STATUS, "Switch2");
delay(100);
gw.present(SWITCH_3_ID, V_STATUS, "Switch3");
delay(100);
gw.present(SWITCH_4_ID, V_STATUS, "Switch4");
delay(100);
gw.present(SWITCH_5_ID, V_STATUS, "Switch5");
delay(100);
gw.present(SWITCH_6_ID, V_STATUS, "Switch6");
delay(100);
gw.present(SWITCH_7_ID, V_STATUS, "Switch7");
delay(100);
gw.present(SWITCH_8_ID, V_STATUS, "Switch8");
delay(100); */
gw.present(CHANNEL_1_ID, V_STATUS, "Channel1");
delay(100);
gw.present(CHANNEL_2_ID, V_STATUS, "Channel2");
delay(100);
gw.present(CHANNEL_3_ID, V_STATUS, "Channel3");
delay(100);
gw.present(CHANNEL_4_ID, V_STATUS, "Channel4");
delay(100);
gw.present(DIMMER_1_ID, V_PERCENTAGE, "Dimmer1");
delay(100);
gw.present(DIMMER_2_ID, V_PERCENTAGE, "Dimmer2");
delay(100);
gw.present(DIMMER_3_ID, V_PERCENTAGE, "Dimmer3");
delay(100);
gw.present(DIMMER_4_ID, V_PERCENTAGE, "Dimmer4");
delay(100);
}
void incomingMessage(const MyMessage &message) {
// Pass along the message from sensors to serial line
//serial(PSTR("%d;%d;%d;%d;%d;%s\n"),message.sender, message.sensor, mGetCommand(message), mGetAck(message), message.type, message.getString(convBuf));
if (mGetCommand(message) == 1) {
if ((message.sensor >= CHANNEL_1_ID) && (message.sensor <= CHANNEL_1_ID+NUM_CHANNELS-1)) {
chState[message.sensor-11] = message.getByte();
gw.send(msg.setSensor(message.sensor).set(chState[message.sensor-11]));
EEPROM.write(CHANNEL_1_ADDR+message.sensor-11, chState[message.sensor-11]);
}
else if ((message.sensor >= DIMMER_1_ID) && (message.sensor <= DIMMER_1_ID+NUM_CHANNELS-1)) {
maxPWM[message.sensor-21] = message.getByte();
gw.send(msg.setSensor(message.sensor).set(maxPWM[message.sensor-21]));
EEPROM.write(DIMMER_1_ADDR+message.sensor-21, maxPWM[message.sensor-21]);
}
else if ((message.sensor >= ALLOW_BRIGHT_1_ID) && (message.sensor <= ALLOW_BRIGHT_1_ID+NUM_CHANNELS-1)) {
allowBright[message.sensor-31] = message.getByte();
gw.send(msg.setSensor(message.sensor).set(allowBright[message.sensor-31]));
EEPROM.write(ALLOW_BRIGHT_1_ADDR+message.sensor-31, allowBright[message.sensor-31]);
}
else if (message.sensor == 255) {
if (message.getByte() == 255) {
configReset();
}
}
}
else if (mGetCommand(message) == 2) {
if ((message.sensor >= CHANNEL_1_ID) && (message.sensor <= CHANNEL_1_ID+NUM_CHANNELS-1)) {
gw.send(msg.setSensor(message.sensor).set(chState[message.sensor-11]));
}
else if ((message.sensor >= DIMMER_1_ID) && (message.sensor <= DIMMER_1_ID+NUM_CHANNELS-1)) {
gw.send(msg.setSensor(message.sensor).set(maxPWM[message.sensor-21]));
}
else if ((message.sensor >= ALLOW_BRIGHT_1_ID) && (message.sensor <= ALLOW_BRIGHT_1_ID+NUM_CHANNELS-1)) {
gw.send(msg.setSensor(message.sensor).set(allowBright[message.sensor-31]));
}
else if ( (message.sensor >= SWITCH_1_ID) && (message.sensor <= SWITCH_1_ID+NUM_SWITCHES-1) ) {
if (PIN_IN[message.sensor-1] <= 13) {
curSwitch[message.sensor-1] = digitalRead(PIN_IN[message.sensor-1]);
} else {
curSwitch[message.sensor-1] = analogRead(PIN_IN[message.sensor-1]);
}
gw.send(msg.setSensor(message.sensor).set(curSwitch[message.sensor-1]));
}
}
}
void setState(byte c, byte n) {
}
void setDimmer(byte c, byte n) {
}
void configReset() {
for (byte i=0; i<NUM_CHANNELS; i++) {
chState[i] = 0;
EEPROM.write(CHANNEL_1_ADDR+i, chState[i]);
}
for (byte i=0; i<NUM_CHANNELS; i++) {
maxPWM[i] = FULL_BRIGHT;
EEPROM.write(DIMMER_1_ADDR+i, maxPWM[i]);
}
}
So I wondered maybe someone here can help me, thanks!