반응형
/*==============================================================================================/
*
* Copyright (C) 2021 ******** Software Corp Reaserch Institute
* All rights reserved.
*
* Author : Lee Kyu Nam (nasanx2001@naver.com)
* Descrition : L2버전
*
*
*
*==============================================================================================*/
#include <time.h>
#include <Crc16.h>
#include <EEPROM.h>
#define u8 unsigned char
#define u16 unsigned short
#define _bit_buff_size 128
#define _write_buff_size 256
#define codesys_addr 0x01
#define pureun_addr 0x01
#define systemid "100003"
/*
* timer
*/
extern volatile unsigned long timer0_millis;
int polling_time = 0;
int old_time = 0;
u16 YYYY = 0;
u8 MM = 0;
u8 DD = 0;
u8 hh = 0;
u8 mm = 0;
u8 ss = 0;
u8 old_mm = 0;
/*
* codesys
*/
u8 codesys_bit_buff[_bit_buff_size] = {0,};
u8 codesys_write_buff[_write_buff_size] = {0,};
u16 codesys_read_point = 0; // serial read point
u16 codesys_last_point = 0; // codesys buff last point
u16 codesys_start_point = 0; // codesys buff start point
u16 codesys_write_point = 0; // codesys write buff point
bool codesys_process = false;
/*
* memory mapping
*/
u16 a_mem[500] = {0,};
u16 b_mem[500] = {0,};
u16 r_mem[500] = {0,};
/*
* digital mapping I/O
*/
// DI
#define WATER_HI 28
#define WATER_LO 29
#define RETURN_WATER_HI 30
#define RETURN_WATER_LO 31
// DO
#define WATER_MAIN_PIN 38
#define WATER_PIN 39
#define RETURN_WATER_PIN 40
#define UV_LAMP_PIN 41
#define PH_PUMP_PIN 42
#define EC_PUMP_PIN 43
/*
* crc
*/
Crc16 crc;
u8 codesys_crc_buff[2];
u8 pureun_crc_buff[2];
/*
* etc
*/
u8 bit_addr[] = {1,2,4,8,16,32,64,128};
u8 uv_flag = 0;
u8 uv_day = 0;
unsigned int ec_time = 0;
u8 ec_flag = 0;
unsigned int ph_time = 0;
u8 ph_flag = 0;
//===================================================================================
void setup(){
u8 i;
Serial.begin(115200);
Serial1.begin(115200, SERIAL_8N1); // codesys
Serial2.begin(115200, SERIAL_8N1); // rasp
for(i=22; i<34; i++){
pinMode(i, INPUT);
}
for(i=34; i<52; i++){
pinMode(i, OUTPUT);
}
Serial.println("============= Start controll process ==============");
}
void loop(){
unsigned long MillisTime = millis();
/*
* 1 sec time check
*/
if(millis() - (MillisTime >= 1000)){
polling_time = millis()/1000;
if(polling_time != old_time){
timer();
digitalWrite(51, !digitalRead(51));
old_time = polling_time;
}
}
/*
* 1 min time check
*/
if(mm != old_mm){
digitalWrite(50, HIGH);
// system get info -> raspberry pi -> get cmd(g)
Serial2.write("g");
digitalWrite(50, LOW);
old_mm = mm;
}
/*
* codesys process (rs232)
*/
codesys_getData();
if(codesys_process == true){
codesys_modbus_process();
}
else{
codesys_process = codesys_getData_frame_check();
}
/*
* raspberry process
*/
rasp_getData();
}
//===================================================================================
/*
* function list
*/
/*****************************************************************
* codesys modbus function *
* *
* **************************************************************/
//===============================================================
// codesys getData
//===============================================================
void codesys_getData(){
if(Serial1.available() > 0){
codesys_bit_buff[codesys_read_point++] = Serial1.read();
codesys_last_point = codesys_read_point-1;
//Serial.print(codesys_bit_buff[codesys_last_point], HEX);
}
}
//===============================================================
// codesys modbus data frame check
//===============================================================
bool codesys_getData_frame_check(){
int i;
u8 Hi, Lo;
// 1. codesys read data -> codesys_id find
if((codesys_bit_buff[codesys_start_point] != codesys_addr) && (codesys_bit_buff[codesys_start_point] != 0)){
codesys_start_point += 1;
return false;
}
else if(codesys_bit_buff[codesys_start_point] == codesys_addr){
if((codesys_last_point - codesys_start_point) > 5){
codesys_Crc16(codesys_bit_buff, codesys_start_point, codesys_last_point-1);
Hi = codesys_bit_buff[codesys_last_point-1];
Lo = codesys_bit_buff[codesys_last_point];
if((Hi == codesys_crc_buff[1]) && (Lo == codesys_crc_buff[0])){
return true;
}
else{
return false;
}
}
else{
return false;
}
}
else{
return false;
}
}
//===============================================================
// codesys modbus crc check
//===============================================================
void codesys_Crc16(u8 *buff, u16 start_point, u16 last_point){
u16 crc_value, i;
memset(codesys_crc_buff, 0x00, 2);
crc_value = crc.Modbus(buff, start_point, last_point);
codesys_crc_buff[0] = crc_value >> 8;
codesys_crc_buff[1] = crc_value;
}
//===============================================================
// codesys move point
//===============================================================
void codesys_move_point(){
codesys_start_point = codesys_last_point+1;
codesys_process = false;
memset(codesys_write_buff, 0x00, sizeof(codesys_write_buff));
codesys_write_point = 0;
// read buff data -> last check -> buff clear
if((codesys_start_point == codesys_read_point) && (codesys_start_point != 0)){
Serial.println("============= codesys last data ==============");
codesys_clear();
}
}
//===============================================================
// codesys buff clear
//===============================================================
void codesys_clear(){
memset(codesys_bit_buff, 0x00, sizeof(codesys_bit_buff));
memset(codesys_write_buff, 0x00, sizeof(codesys_write_buff));
codesys_read_point = 0;
codesys_last_point = 0;
codesys_start_point = 0;
codesys_write_point = 0;
codesys_process = false;
}
//===============================================================
// codesys put byte
//===============================================================
void codesys_putByte(u8 data){
Serial1.write(data);
codesys_write_buff[codesys_write_point++] = data;
}
//===============================================================
// codesys put word
//===============================================================
void codesys_putWord(u16 data){
u8 Hi, Lo;
Serial1.write(data >> 8);
Serial1.write(data);
codesys_write_buff[codesys_write_point++] = (data >> 8);
codesys_write_buff[codesys_write_point++] = data;
}
//===============================================================
// codesys get word
//===============================================================
u16 codesys_getWord(u16 num){
u8 wh, wl;
wh = codesys_bit_buff[num];
wl = codesys_bit_buff[num+1];
return (wh<<8)+wl;
}
//===============================================================
// codesys read memory -> make bit -> send codesys
//===============================================================
u8 codesys_bit_mem(u16 addr, u16 len)
{
u8 i, j, k=0, val=0;
u16 pin;
for(i=0; i<len; i++){
pin = r_mem[addr];
if(pin == 1){
if(i > 0){
val += (1 << i);
}
if(i == 0){
k = 1;
}
}
addr++;
}
return (val+k);
}
//===============================================================
// codesys modbus process
//===============================================================
void codesys_modbus_process(){
u8 i, num=0;
u8 slave_addr, fc;
slave_addr = codesys_bit_buff[num++];
fc = codesys_bit_buff[num++];
switch(fc){
case 1:
case 2:
codesys_read_bit();
break;
case 3:
codesys_read_word();
break;
case 5:
codesys_write_bit_single();
break;
case 6:
codesys_write_word_single();
break;
case 15:
codesys_write_bit_multiple();
break;
case 16:
codesys_write_word_multiple();
break;
default:
break;
}
Serial.print("codesys read Data : ");
for(i=codesys_start_point; i<=codesys_last_point; i++){
Serial.print(codesys_bit_buff[i], HEX);
Serial.print(" ");
}
Serial.println();
codesys_move_point();
}
//===============================================================
// codesys modbus function code 1,2
//===============================================================
void codesys_read_bit(){
u8 i, j=0, fc, blen, pin=0;
u16 len, addr;
fc = codesys_bit_buff[1];
addr = codesys_getWord(2);
len = codesys_getWord(4);
//return data
codesys_putByte(codesys_addr);
codesys_putByte(fc);
blen = len >> 3;
if (len & 7) blen++;
codesys_putByte(blen);
for(i=0; i<blen; i++){
j = codesys_bit_mem(addr, len);
digital_read_mapping(addr);
codesys_putByte(j);
addr += 8;
len -= 8;
}
codesys_Crc16(codesys_write_buff, 0, codesys_write_point);
codesys_putByte(codesys_crc_buff[1]);
codesys_putByte(codesys_crc_buff[0]);
/*
Serial.print("codesys write data : ");
for(int k=0; k<codesys_write_point; k++){
Serial.print(codesys_write_buff[k] ,HEX);
Serial.print(" ");
}
Serial.println();
*/
memset(codesys_write_buff, 0x00, sizeof(codesys_write_buff));
codesys_write_point = 0;
}
//===============================================================
// codesys modbus function code 3
//===============================================================
void codesys_read_word(){
u8 i, k, fc, count=0;
u16 addr, addr_save, len, j, val;
u16 crc_value;
fc = codesys_bit_buff[1];
addr = codesys_getWord(2);
len = codesys_getWord(4);
codesys_putByte(codesys_addr);
codesys_putByte(fc);
k = len << 1;
codesys_putByte(k);
for(j=0; j<len; j++){
val = a_mem[addr];
codesys_putWord(val);
addr++;
}
codesys_Crc16(codesys_write_buff, 0, codesys_write_point);
codesys_putByte(codesys_crc_buff[1]);
codesys_putByte(codesys_crc_buff[0]);
/*
Serial.print("codesys write Data : ");
for(i=0; i<codesys_write_point; i++){
Serial.print(codesys_write_buff[i], HEX);
Serial.print(" ");
}
Serial.println();
*/
memset(codesys_write_buff, 0x00, sizeof(codesys_write_buff));
codesys_write_point = 0;
}
//===============================================================
// codesys modbus function code 5
//===============================================================
void codesys_write_bit_single(){
u8 i, fc;
u16 val, addr, addr_save, pin_num;
fc = codesys_bit_buff[1];
addr_save = addr = codesys_getWord(2);
val = codesys_getWord(4);
addr = codesys_stick_controll(addr, val);
if(addr <= 500){
digitalWrite(addr, (val>>8) & 0xFF ? HIGH : LOW);
}
Serial.println(addr, DEC);
digital_read_mapping(addr);
//return data
codesys_putByte(codesys_addr);
codesys_putByte(fc);
codesys_putWord(addr_save);
codesys_putWord(val);
codesys_Crc16(codesys_write_buff, 0, codesys_write_point);
codesys_putByte(codesys_crc_buff[1]);
codesys_putByte(codesys_crc_buff[0]);
}
//===============================================================
// codesys modbus function code 6
//===============================================================
void codesys_write_word_single(){
u8 i, fc;
u16 addr, val;
fc = codesys_bit_buff[1];
addr = codesys_getWord(2);
val = codesys_getWord(4);
codesys_word_input(addr, val);
//return data
codesys_putByte(codesys_addr);
codesys_putByte(fc);
codesys_putWord(addr);
codesys_putWord(val);
codesys_Crc16(codesys_write_buff, 0, codesys_write_point);
codesys_putByte(codesys_crc_buff[1]);
codesys_putByte(codesys_crc_buff[0]);
}
//===============================================================
// codesys modbus function code 15
//===============================================================
void codesys_write_bit_multiple(){
u8 i, j, fc, cnt;
u16 addr, addr_save, len, len_save;
fc = codesys_bit_buff[1];
addr_save = addr = codesys_getWord(2);
len_save = len = codesys_getWord(4);
cnt = codesys_bit_buff[6];
for(i=0; i<cnt; i++){
j = codesys_bit_buff[7];
arduino_writebits(addr, j, len, codesys_bit_buff);
addr += 8;
len -= 8;
}
codesys_putByte(codesys_addr);
codesys_putByte(fc);
codesys_putByte(addr_save);
codesys_putByte(len_save);
codesys_Crc16(codesys_write_buff, 0, codesys_write_point);
codesys_putByte(codesys_crc_buff[1]);
codesys_putByte(codesys_crc_buff[0]);
}
//===============================================================
// codesys modbus function code 16
//===============================================================
void codesys_write_word_multiple(){
u8 fc, cnt;
u16 addr, addr_save, len, val, i, num;
fc = codesys_bit_buff[1];
addr_save = addr = codesys_getWord(2);
len = codesys_getWord(4);
cnt = codesys_bit_buff[6];
for(i=0; i<len; i++){
num = 7+(i*2);
val = codesys_getWord(num);
a_mem[addr] = val;
addr++;
}
codesys_putByte(codesys_addr);
codesys_putByte(fc);
codesys_putByte(addr_save);
codesys_putByte(len);
codesys_Crc16(codesys_write_buff, 0, codesys_write_point);
codesys_putByte(codesys_crc_buff[1]);
codesys_putByte(codesys_crc_buff[0]);
}
//===============================================================
// codesys digital read mapping (D/O)
//===============================================================
void digital_read_mapping(u16 addr){
u16 val;
switch(addr){
case UV_LAMP_PIN:
val = digitalRead(UV_LAMP_PIN);
r_mem[73] = val;
break;
case EC_PUMP_PIN:
val = digitalRead(EC_PUMP_PIN);
r_mem[75] = val;
break;
case PH_PUMP_PIN:
val = digitalRead(PH_PUMP_PIN);
r_mem[76] = val;
break;
case WATER_MAIN_PIN:
val = digitalRead(WATER_MAIN_PIN);
r_mem[85] = val;
break;
case WATER_PIN:
val = digitalRead(WATER_PIN);
r_mem[101] = val;
break;
case RETURN_WATER_PIN:
val = digitalRead(RETURN_WATER_PIN);
r_mem[111] = val;
break;
default:
break;
}
}
//===============================================================
// codesys digital stick controll
//===============================================================
u16 codesys_stick_controll(u16 addr, u16 val){
switch(addr){
case 1073:
b_mem[addr-1000] = 0;
addr = UV_LAMP_PIN;
break;
case 1075:
b_mem[addr-1000] = 0;
addr = EC_PUMP_PIN;
break;
case 1076:
b_mem[addr-1000] = 0;
addr = PH_PUMP_PIN;
break;
case 1101:
b_mem[addr-1000] = 0;
addr = WATER_PIN;
break;
case 1111:
b_mem[addr-1000] = 0;
addr = RETURN_WATER_PIN;
break;
default:
break;
}
return addr;
}
//===============================================================
// codesys analog mapping input
//===============================================================
void codesys_word_input(u16 addr, u16 val){
u16 addr_save;
addr_save = (addr - 250);
a_mem[addr_save] = val;
a_mem[addr] = 0;
Serial.print("addr_save, val : ");
Serial.print(addr_save, DEC);
Serial.print(", ");
Serial.println(a_mem[addr_save], DEC);
}
/*****************************************************************
* raspberry pi function *
* *
* **************************************************************/
//===============================================================
// raspberry getData
//===============================================================
void rasp_getData(){
while(Serial2.available() > 0){
String str = Serial2.readStringUntil('\n');
str.toCharArray(rasp_buff, str.length()+1);
if(rasp_buff[0] == 't'){
getTime();
}
if(rasp_buff[0] == 'g'){
t_farm_getData();
}
}
}
/*****************************************************************
* etc function *
* *
* **************************************************************/
//===============================================================
// arduino wirte bit controll
//===============================================================
void arduino_writebits(u16 addr, u8 val, u8 len, u8 *buff){
u8 i,m;
if (len > 7){
m=8;
}
else{
m=len; // 15인 경우도 8개씩 나누어서 처리
}
for (i=0;i<m;i++) { // 8번 (마지막에서는 8번 미만) 돌면서, buffer의 내용을 수정한다.
if (val & bit_addr[i]){ // (adr에 byte어드레스와 bit어드레스 모두 포함되어 있다.)
buff[addr >> 3] |= bit_addr[addr & 7];
digitalWrite(addr, HIGH);
}
else{
buff[addr >> 3] &= ~bit_addr[addr & 7];
digitalWrite(addr, LOW);
}
addr++;
}
}
//===============================================================
// timer
//===============================================================
void timer(){
if((ss == 0) && (mm == 0) && (hh == 0)){
timer0_millis = 0;
// timer get info -> raspberry pi -> get cmd(t)
Serial2.write('t');
}
ss++;
if(ss >= 60){
ss = 0;
++mm;
if(mm >= 60){
mm = 0;
++hh;
if(hh >= 24){
hh = 0;
}
}
}
Serial.println();
Serial.print(hh, DEC);
Serial.print(":");
Serial.print(mm, DEC);
Serial.print(":");
Serial.print(ss, DEC);
Serial.println();
a_mem[0] = hh;
a_mem[1] = mm;
a_mem[2] = ss;
}
//===============================================================
// rasp time info get
//===============================================================
void getTime(){
char *p;
int i=0;
String tmp;
p = strtok(rasp_buff, ", ");
while(p != NULL)
{
if((strcmp(p, "t") != 0))
{
i++;
tmp = p;
switch(i){
case 1: YYYY = tmp.toInt(); break;
case 2: MM = tmp.toInt(); break;
case 3: DD = tmp.toInt(); break;
case 4: a_mem[0] = hh = tmp.toInt(); break;
case 5: a_mem[1] = mm = tmp.toInt(); break;
case 6: a_mem[2] = ss = tmp.toInt(); break;
}
}
p = strtok(NULL, ", ");
}
memset(rasp_buff, 0x00, sizeof(rasp_buff));
}
공개할수 없는 부분들도 있어서 이것저것 바꿔서 올리다보니 안맞는 부분이 많을수도 있다..
코드는 modbus 관련한 부분만 가져다가 수정해서 써보는걸로.. 공부도 될겸
728x90
반응형