#include <Arduino.h>
#include <Bounce.h>
#include <EEPROM.h>
/*
Модуль управления светом на семь групп "MUS-7" управляемый по RS-485
0x03 (03) - чтение значени из регистров хранения
0x10 (16) - запись значения в регистр хранения
0x48 (72) - смена адресса устройства
00 7f 10 00 00 00 01 00 02 00 92 - запись значениия "2" в регистр №0
00 7f 10 00 00 00 02 00 01 00 01 00 93 - запись значениия "1" в регистр №0 и №1
00 7f 03 00 00 00 07 00 89 - чтение всех 7-ми регистров га устройстве по адресу 127 (0x7f)
00 7f 48 00 00 00 01 00 02 00 ca - смена адресса устройства с 127 на 2 с записью в энергонезависимую память
*/
#define SerialTxControl 10 //RS485 порт управления max485 arduino pin 10
#define RS485Transmit HIGH // включение режима передачи
#define RS485Receive LOW // сключение режима приема
const int ledDan = 13; // выход индикации на включение режима передачи
int address_read;
int address;
int address_buf;
int funct; // функция
long date[100];
int col_dan; // the variable for counting the number of transmitted registers
int stat = 0;
int checksum;
int sum;
int sum_dan = 0;
int s_reg;
int val_a[] ={0,0,0,0,0,0,0}; // служебные регистры
int val_b[] ={0,0,0,0,0,0,0}; // буферные принимаемые регистры
int valOld[] ={0,0,0,0,0,0,0}; // старое значение регистров
// задание портов выводов подключаемых к реле
const int ledPin2 = 9;
const int ledPin3 = 8;
const int ledPin4 = 7;
const int ledPin5 = 6;
const int ledPin6 = 5;
const int ledPin7 = 4;
const int ledPin8 = 3;
// задание портов входов подключения к выключателям
const int analogInPin2 = 12;
const int analogInPin3 = A0;
const int analogInPin4 = A1;
const int analogInPin5 = A2;
const int analogInPin6 = A3;
const int analogInPin7 = A4;
const int analogInPin8 = A5;
// устранение дребезга контактов
Bounce bouncer2 = Bounce( analogInPin2, 10 );
Bounce bouncer3 = Bounce( analogInPin3, 10 );
Bounce bouncer4 = Bounce( analogInPin4, 10 );
Bounce bouncer5 = Bounce( analogInPin5, 10 );
Bounce bouncer6 = Bounce( analogInPin6, 10 );
Bounce bouncer7 = Bounce( analogInPin7, 10 );
Bounce bouncer8 = Bounce( analogInPin8, 10 );
void setup()
{
Serial.begin(9600);
delay(100);
address_read = EEPROM.read(0);
if (address_read == 255) {
address = 127;
}
else {address = address_read;}
pinMode(SerialTxControl, OUTPUT);
pinMode(ledDan, OUTPUT);
digitalWrite(SerialTxControl, RS485Transmit);
digitalWrite(ledDan, RS485Transmit);
Serial.println("");
Serial.print("Address - ");
Serial.print(address);
Serial.print(" ");
Serial.print("MUS-7");
Serial.print(" ");
Serial.print("(OKbit.ru)");
Serial.println(" ");
delay(100);
digitalWrite(SerialTxControl, RS485Receive);
digitalWrite(ledDan, RS485Receive);
pinMode(ledPin2, OUTPUT);
pinMode(ledPin3, OUTPUT);
pinMode(ledPin4, OUTPUT);
pinMode(ledPin5, OUTPUT);
pinMode(ledPin6, OUTPUT);
pinMode(ledPin7, OUTPUT);
pinMode(ledPin8, OUTPUT);
pinMode(analogInPin2,INPUT);
pinMode(analogInPin3,INPUT);
pinMode(analogInPin4,INPUT);
pinMode(analogInPin5,INPUT);
pinMode(analogInPin6,INPUT);
pinMode(analogInPin7,INPUT);
pinMode(analogInPin8,INPUT);
}
void fBus_read(){
funct = 0;
col_dan = 0;
sum_dan = 0;
sum = 0;
if (Serial.available() > 0 && stat == 0 )
{
for(int i=0; i < 300; i++)
{
delay(10);
date[i] = Serial.read();
if (i == 6)
{
col_dan = ((date[6] << 0) & 0xFF) + ((date[5] << 8) & 0xFF00);
}
//Serial.write(col_dan);
//Serial.write(date[i]);
if (i == col_dan*2+8)
{
stat = 1;
break;
}
}
funct = date[2];
s_reg = ((date[4] << 0) & 0xFF) + ((date[3] << 8) & 0xFF00); // вычисление значения сдвигового регистра
// вычисление значения чексуммы
checksum = ((date[8+col_dan*2] << 0) & 0xFF) + ((date[7+col_dan*2] << 8) & 0xFF00);
//считывание значений регистров и их суммы если функция команды на запись "0x10"
//или функция смены адресса устройства "0x03"
if (funct == 0x10){
for (int a=0; a <= col_dan-1; a++)
{
val_b[a+s_reg] = (((date[8+a*2] << 0) & 0xFF) + ((date[7+a*2] << 8) & 0xFF00));
sum_dan = sum_dan + (((date[8+a*2] << 0) & 0xFF) + ((date[7+a*2] << 8) & 0xFF00));
}
// вычисление суммы для проверки целосности
sum = date[1] + date[2] + s_reg + col_dan + sum_dan;
// вычисление значения чексуммы
checksum = ((date[8+col_dan*2] << 0) & 0xFF) + ((date[7+col_dan*2] << 8) & 0xFF00);
}
//вычесление суммы данных для фунции чтения значения регистров "0x03"
else if (funct == 0x03){
for (int a=0; a <= col_dan-1; a++)
{
sum_dan = sum_dan + val_b[a+s_reg];
}
// вычисление значения чексуммы
checksum = ((date[8] << 0) & 0xFF) + ((date[7] << 8) & 0xFF00);
// вычисление суммы для команды чтения регистра
sum = date[1] + date[2] + s_reg + col_dan;
}
//вычесление суммы данных для фунции чтения значения регистров "0x48"
else if (funct == 0x48){
address_buf = (((date[8] << 0) & 0xFF) + ((date[7] << 8) & 0xFF00));
// вычисление значения чексуммы
checksum = ((date[10] << 0) & 0xFF) + ((date[9] << 8) & 0xFF00);
// вычисление суммы для команды смены адресса
sum = date[1] + date[2] + s_reg + col_dan + address_buf;
}
// проверка что пакет пришел по протоколу fBus данному адресату и пакет целый не битый
if (date[0] == 0 && date[1] == address && checksum == sum)
{
stat = 2;
if (funct == 0x03){sum = date[1] + date[2] + s_reg + col_dan + sum_dan;}
}
else
{
stat = 1;
}
}
// Отчистка серийного буфера от мусора если таковой есть
if (Serial.available() > 0 && stat == 1)
{
delay(10);
int zero = Serial.read();
}
else if (stat == 1){
stat = 0;
}
}
void fBus_write(){
if (stat == 2)
{
delay(100);
digitalWrite(SerialTxControl, RS485Transmit);
digitalWrite(ledDan, RS485Transmit);
Serial.write(0x00);
Serial.write(address);
Serial.write(funct);
Serial.write(((s_reg >> 8) & 0xFF));
Serial.write(((s_reg >> 0) & 0xFF));
Serial.write(((col_dan >> 8) & 0xFF));
Serial.write(((col_dan >> 0) & 0xFF));
if (funct == 0x10 || funct == 0x03){
for (int a=0; a <= col_dan-1; a++)
{
delay(1);
Serial.write((val_b[a+s_reg] >> 8) & 0xFF);
Serial.write((val_b[a+s_reg] >> 0) & 0xFF);
}
}
if (funct == 0x48){
Serial.write((address_buf >> 8) & 0xFF);
Serial.write((address_buf >> 0) & 0xFF);
}
Serial.write(((sum >> 8) & 0xFF));
Serial.write(((sum >> 0) & 0xFF));
stat = 1;
delay(100);
digitalWrite(SerialTxControl, RS485Receive);
digitalWrite(ledDan, RS485Receive);
}
}
void debounce(){
if ( bouncer2.update() ) {
if ( bouncer2.read() == HIGH) {
if ( val_a[0] == LOW ) {
val_a[0] = HIGH;
} else {
val_a[0] = LOW;
}
valOld[0] = val_a[0];
val_b[0] = val_a[0];
}
}
digitalWrite(ledPin2,val_a[0]);
if ( bouncer3.update() ) {
if ( bouncer3.read() == HIGH) {
if ( val_a[1] == LOW ) {
val_a[1] = HIGH;
} else {
val_a[1] = LOW;
}
valOld[1] = val_a[1];
val_b[1] = val_a[1];
}
}
digitalWrite(ledPin3,val_a[1]);
if ( bouncer4.update() ) {
if ( bouncer4.read() == HIGH) {
if ( val_a[2] == LOW ) {
val_a[2] = HIGH;
} else {
val_a[2] = LOW;
}
valOld[2] = val_a[2];
val_b[2] = val_a[2];
}
}
digitalWrite(ledPin4,val_a[2]);
if ( bouncer5.update() ) {
if ( bouncer5.read() == HIGH) {
if ( val_a[3] == LOW ) {
val_a[3] = HIGH;
} else {
val_a[3] = LOW;
}
valOld[3] = val_a[3];
val_b[3] = val_a[3];
}
}
digitalWrite(ledPin5,val_a[3]);
if ( bouncer6.update() ) {
if ( bouncer6.read() == HIGH) {
if ( val_a[4] == LOW ) {
val_a[4] = HIGH;
} else {
val_a[4] = LOW;
}
valOld[4] = val_a[4];
val_b[4] = val_a[4];
}
}
digitalWrite(ledPin6,val_a[4]);
if ( bouncer7.update() ) {
if ( bouncer7.read() == HIGH) {
if ( val_a[5] == LOW ) {
val_a[5] = HIGH;
} else {
val_a[5] = LOW;
}
valOld[5] = val_a[5];
val_b[5] = val_a[5];
}
}
digitalWrite(ledPin7,val_a[5]);
if ( bouncer8.update() ) {
if ( bouncer8.read() == HIGH) {
if ( val_a[6] == LOW ) {
val_a[6] = HIGH;
} else {
val_a[6] = LOW;
}
valOld[6] = val_a[6];
val_b[6] = val_a[6];
}
}
digitalWrite(ledPin8,val_a[6]);
}
void handler(){
if (stat == 2 && funct == 0x10){
//проверка пришедших значений регистра, если значение неравно старому переключить значение выхода
if (val_b[0] != valOld[0]){ val_a[0] = val_b[0];
valOld[0] = val_b[0];
}
if (val_b[1] != valOld[1]){ val_a[1] = val_b[1];
valOld[1] = val_b[1];
}
if (val_b[2] != valOld[2]){ val_a[2] = val_b[2];
valOld[2] = val_b[2];
}
if (val_b[3] != valOld[3]){ val_a[3] = val_b[3];
valOld[3] = val_b[3];
}
if (val_b[4] != valOld[4]){ val_a[4] = val_b[4];
valOld[4] = val_b[4];
}
if (val_b[5] != valOld[5]){ val_a[5] = val_b[5];
valOld[5] = val_b[5];
}
if (val_b[6] != valOld[6]){ val_a[6] = val_b[6];
valOld[6] = val_b[6];
}
}
}
void check_address(){
if (stat == 2 && funct == 0x48 && address != address_buf){
address = ((address_buf >> 0) & 0xFF);
EEPROM.write(0, address);
}
}
void loop(){
fBus_read();
check_address();
debounce();
handler();
fBus_write();
}