хорошо, вот весь код
#include <Arduino.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 16000000
short layer_pot, reel_pot;
volatile short old_layer_value, old_reel_value;
#define rx_pin PD0 //uart recive
#define tx_pin PD1 //uart trancive
#define OVERLOAD PD3 // INT0 interrupt connected
#define STOP PD2 // INT1 interrupt connected
#define RIGHT PD6 // layer direction right button
#define LEFT 9 // layer direction left button
#define UP 17 // reel direction up button
#define LED_UP 16 //LED in button
#define DOWN 15 //reel direction down button
#define LED_DOWN 14 //LED in button
#define ADC_REEL 20 // potentiometr pin for control speed on reel motor
#define ADC_LAYER 21 // potentiometr pin for control speed on layer motor
unsigned char data[8] = {
0x01, //device address
0x06, //write mode
0xAB, //HIGH register address
0xCD, //LOW register address
0xAB, //HIGH register value
0xCD, //LOW register value
0x00, //HIGH CRC
0x00 //LOW CRC
};
void load_pin(void){
pinMode(UP, INPUT_PULLUP);
pinMode(DOWN, INPUT_PULLUP);
pinMode(LED_UP, OUTPUT);
pinMode(LED_DOWN, OUTPUT);
pinMode(LEFT, INPUT_PULLUP);
pinMode(RIGHT, INPUT_PULLUP);
pinMode(STOP, INPUT);
pinMode(OVERLOAD, INPUT);
pinMode(ADC_REEL, INPUT);
pinMode(ADC_LAYER, INPUT);
// return;
}
void load(void){
//attach interrupt for pins OVERLOAD and STOP
EIMSK |= (1 << INT0) | (1 << INT1);
EICRA |= (1 << ISC11) | (0 << ISC10) | (1 << ISC01) | (0 << ISC00); // falling change 1 -> 0
Serial.begin(9600); //setup uart (default setup)
Serial.setTimeout(1000);
sei(); //enable interrupts
//return;
}
volatile bool no_change = false;
ISR(INT0_vect){ //STOP button interrupt
sendCommand(0x00,0x00,0x00,0x00,0x00); //shutdown all devices
no_change = false;
digitalWrite(LED_DOWN, LOW);
digitalWrite(LED_UP, LOW);
//return;
}
ISR(INT1_vect){ //OVERLOAD
sendCommand(0x00,0x00,0x00,0x00,0x00); //shutdown all devices
no_change = false;
digitalWrite(LED_DOWN, LOW);
digitalWrite(LED_UP, LOW);
//return;
}
int main(void) {
init();
load_pin();
load();
while(1){
check_keyboard();
check_pots();
}
return 0;
}
//for save values in high and low bits
unsigned char* data_layer_speed;
unsigned char* data_reel_speed;
#define DELTA 100
void check_pots(void){
reel_pot = analogRead(ADC_REEL);
int16_t reel_value = map(reel_pot, 0, 1023, 0, 5000);
if(abs(reel_value - old_reel_value) > DELTA){ // if values from potentiometr reel changed refresh freqency on slave devices
data_reel_speed = decimalTo2ComponentHex(reel_value);
sendCommand(0x01,0x00,0x01,data_reel_speed[0],data_reel_speed[1]);
old_reel_value = reel_value;
}
layer_pot = analogRead(ADC_LAYER) + 0.2*reel_pot;
int16_t layer_value = map(layer_pot, 0, 1023, 0, 5000);
if(abs(layer_value - old_layer_value) > DELTA){ // if values from potentiometr layer changed refresh freqency on slave devices
data_layer_speed = decimalTo2ComponentHex(layer_value);
sendCommand(0x02,0x00,0x01,data_layer_speed[0],data_layer_speed[1]);
old_layer_value = layer_value;
}
}
bool click = false;
byte counter = 0;
void check_keyboard(void){ // maybe switch case?
if(!digitalRead(UP) && !no_change){
sendCommand(0x00,0x00,0x00,0x00,0x01); // all device start, (reel and layer drivers)
no_change = true; // forbidding flag
digitalWrite(LED_UP, HIGH); //enable LED
}
else if(!digitalRead(DOWN) && !no_change){
sendCommand(0x00,0x00,0x00,0x00,0x02); // all device start reverse, (reel and layer drivers)
no_change = true; // forbidding flag
digitalWrite(LED_DOWN, HIGH); //enable LED
}
else if(!digitalRead(LEFT) && !click){
counter++;
layer_driver(false);
click = true;
}
else if(!digitalRead(RIGHT) && !click){
counter++;
layer_driver(true);
click = true;
}
else if(click && digitalRead(RIGHT) && digitalRead(LEFT)){
sendCommand(0x02,0x00,0x00,0x00,0x00); //device shutdown
click = false;
counter = 0;
}
}
void layer_driver(bool dir){
if(counter == 1){ // when command not send, flag start not be false
if(!dir){
sendCommand(0x02,0x00,0x00,0x00,0x02); //device start in reverse
sendCommand(0x02,0x00,0x01,0x13,0x88); //set max freqency
}
else{
sendCommand(0x02,0x00,0x00,0x00,0x01); //device start
sendCommand(0x02,0x00,0x01,0x13,0x88); //set max freqency
}
}
}
uint16_t crc_16_modbus = 0xFFFF;
void sendCommand(char address, char HI_address, char LO_address, char HI_value, char LO_value){
//make command array
data[0] = address;
data[2] = HI_address;
data[3] = LO_address;
data[4] = HI_value;
data[5] = LO_value;
unsigned char buf[6] = {data[0], data[1], data[2], data[3], data[4], data[5]};
//calculate CRC value
crc_16_modbus = GetCrc16Simple(buf, sizeof(buf));
//update CRC
data[6] = (crc_16_modbus >> 8) & 0xFF;
data[7] = crc_16_modbus & 0xFF;
//send package modbus
for(byte i = 0; i<sizeof(data); i++){
Serial.write(data[i]);
}
Serial.flush();
delay(10);
}
uint16_t GetCrc16Simple(uint8_t * data, uint16_t len){
uint8_t lo;
union{
uint16_t value;
struct { uint8_t lo, hi;} bytes;
} crc;
crc.value = 0xFFFF;
while(len--){
lo = crc.bytes.hi;
crc.bytes.lo = crc.bytes.hi;
crc.bytes.hi = lo ^ *data++;
uint8_t mask = 1;
if(crc.bytes.hi & mask) crc.value ^= 0x0240;
if ( crc.bytes.hi & ( mask << 1 ) ) crc.value ^= 0x0480;
if ( crc.bytes.hi & ( mask << 2 ) ) crc.bytes.hi ^= 0x09;
if ( crc.bytes.hi & ( mask << 3 ) ) crc.bytes.hi ^= 0x12;
if ( crc.bytes.hi & ( mask << 4 ) ) crc.bytes.hi ^= 0x24;
if ( crc.bytes.hi & ( mask << 5 ) ) crc.bytes.hi ^= 0x48;
if ( crc.bytes.hi & ( mask << 6 ) ) crc.bytes.hi ^= 0x90;
if ( crc.bytes.hi & ( mask << 7 ) ) crc.value ^= 0x2001;
}
return crc.value;
}
unsigned char* decimalTo2ComponentHex(unsigned int decimalNum) {
unsigned char* result = new unsigned char[2];
result[0] = (decimalNum >> 8) & 0xFF;
result[1] = decimalNum & 0xFF;
return result;
}