[Command 및 Process 중간 완료]

- Ethernet을 통한 명령
  ㄴ DO!, DI?, AI?, SV!, SV?, PV?
  ㄴ AT!(MC9 AutoTune): 테스트 완료, 주석으로 정리해 놨음
  ㄴ AO!: DAC 수령 후 작성 예정
- Buffer
  ㄴ Write는 CRLF 확인 후 없으면 CRLF 추가 후 write
  ㄴ Read는 CRLF 까지 데이터를 출력, CRLF는 미출력으로 필요시 read후 추가 필요
  ㄴ 즉, Buffer는 CRLF를 기준으로 쓰기/읽기 진행, 기본적으로 입출력시 CRLF 제외되나, 저장시 CRLF 있는 경우 중복방지처리 됨
main
Changwoo Park 2 years ago
parent 8429349d1b
commit 7036eb5629

Binary file not shown.

@ -65,7 +65,7 @@ String demuxCMD(String command, String* rightPart) {
// ":"를 기준으로 문자열을 분리 // ":"를 기준으로 문자열을 분리
int separatorIndex = command.indexOf(":"); int separatorIndex = command.indexOf(":");
String leftPart = command.substring(0, separatorIndex); String leftPart = command.substring(0, separatorIndex);
*rightPart = command.substring(separatorIndex + 2); *rightPart = command.substring(separatorIndex + 1);
leftPart.replace(" ", ""); leftPart.replace(" ", "");
return leftPart; return leftPart;
@ -95,6 +95,5 @@ int demuxNum(String rightPart, unsigned int data[]) {
data[index] = strtoul(hexValue.c_str(), NULL, 16); data[index] = strtoul(hexValue.c_str(), NULL, 16);
index++; index++;
// 왼쪽 부분인 "ABC"을 반환
return index; return index;
} }

@ -3,13 +3,14 @@
#include <avr/wdt.h> // ?? #include <avr/wdt.h> // ??
//#include "SC_AI.h" // Differential analog input collector
//#include "SC_MC9.h" // MC9 Tempreture Controller
#define CRLF "\r\n"
#define RcvOK "OK\r\n" #define RcvOK "OK\r\n"
#define RcvErr "ER\r\n" #define RcvErr "ER\r\n"
#define MODE_DEBUG false #define MODE_DEBUG false
String IdeSerial;
const int BUFF_SIZE = 512; const int BUFF_SIZE = 512;
char Buff_Eth_Rd[BUFF_SIZE] = {0}; char Buff_Eth_Rd[BUFF_SIZE] = {0};
char Buff_485_Wr[BUFF_SIZE] = {0}; char Buff_485_Wr[BUFF_SIZE] = {0};
@ -52,6 +53,15 @@ int Wait_485_cnt;
// ========== ========== Processing // ========== ========== Processing
// Read Datas // Read Datas
const int DoPin[] = { 26, 27, 28, 29, 30, 31, 32, 33,
34, 35, 36, 37, 38, 39, 40, 41};
const int DiPin[] = { 2, 3, 4, 5, 6, 7, 8, 9};
const int AiPin[] = { A0, A1, A2, A3, A4, A5, A6, A7,
A8, A9, A10, A11, A12, A13, A14, A15};
int Size_DO = 16;
int Size_DI = 8;
int Values_DI;
int Size_AI = 16; int Size_AI = 16;
int Values_AI[16]; int Values_AI[16];
int Size_PV = 8; int Size_PV = 8;
@ -111,17 +121,6 @@ void loop() {
write_buff_c(Buff_Eth_Rd, c); write_buff_c(Buff_Eth_Rd, c);
} }
/*
//If endwith CRLF
if((c == 10) && (Buf_eth.endsWith("\r"))){
Buf_eth.remove(Buf_eth.length() - 1); //remove CR
message = Buf_eth;
Buf_eth = "";
break;
}else{
Buf_eth += c;
}
*/
} }
// 데이터를 수신했으므로 타임아웃 타이머 초기화 // 데이터를 수신했으므로 타임아웃 타이머 초기화
lastDataReceivedTime = millis(); lastDataReceivedTime = millis();
@ -132,7 +131,14 @@ void loop() {
cmd = demuxCMD(message, &cmdData); cmd = demuxCMD(message, &cmdData);
message = ""; message = "";
if(cmd=="AI?"){ if(cmd=="DO!"){
dataSize = demuxNum(cmdData, data);
client.print(Prcss_DO_Write(data, dataSize));
}else if(cmd=="DI?"){
client.print(Prcss_DI_Read());
}else if(cmd=="AI?"){
client.print(Prcss_AI_Read()); client.print(Prcss_AI_Read());
}else if(cmd=="AO!"){ }else if(cmd=="AO!"){
@ -146,6 +152,7 @@ void loop() {
client.print(Prcss_SV_Read()); client.print(Prcss_SV_Read());
}else if(cmd=="SV!"){ }else if(cmd=="SV!"){
Serial.println(cmdData);
dataSize = demuxNum(cmdData, data); dataSize = demuxNum(cmdData, data);
client.print(Prcss_SV_Write(data, dataSize)); client.print(Prcss_SV_Write(data, dataSize));

@ -1,14 +1,25 @@
const int aipin[] = {A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15};
void GPIO_setup(){ void GPIO_setup(){
for (int i = 0; i < Size_DI; i++) {
pinMode(DiPin[i], INPUT);
}
for (int i = 0; i < Size_DO; i++) {
pinMode(DoPin[i], OUTPUT);
}
} }
void read_analog(){ void read_analog(){
int i = 0; int i = 0;
for(i = 0 ; i < Size_AI ; i++){ for(i = 0 ; i < Size_AI ; i++){
Values_AI[i] = analogRead(aipin[i]); Values_AI[i] = analogRead(AiPin[i]);
} }
}
}
void read_digital(){
int i = 0;
Values_DI = 0;
for(i = 0 ; i < Size_DI ; i++){
bitWrite(Values_DI, i, digitalRead(DiPin[i]));
}
}

@ -1,63 +1,44 @@
const int MC9_CH[] = {1000, 1008, 1016, 1024, 1100, 1108, 1116, 1124};
/* #define MC9_10_PV "10DRS,08,0001CB"
void read_mc9_req(String address){ #define MC9_10_SV "10DRS,08,0011CC"
if(!Wait_485){
String command = "";
command += address;
command += "DRS,03,0011C7\r\n";
// Send request to return pv data
digitalWrite(RS485_OE_1, Snd_485); delay(5);
Serial1.print(command);
Serial1.flush();
digitalWrite(RS485_OE_1, Rcv_485); delay(5);
Wait_485 = true;
Wait_485_cnt = 0;
}
}
void read_mc9(int arr[], int size){ // 10DWR,02,0302,0001,0501,0001
char c; // Auto Tune. 0302(Ch Sel) 0001(Ch.1) 0501(AT) 0001(On, Off=0000)
String message;
// Timeout code int parseMC9(const String& message, int& addr, String& mode, int data[8], int& crc) {
if(Wait_485){ char addrC[3], modeC[4], statusC[3];
Wait_485_cnt++; int dataC[8], crcC;
if(Wait_485_cnt > 10){ // Timeout = periodic(10ms) x 10 = 10 msec
Wait_485 = false; if (message[0] == '\x02') {
Wait_485_cnt = 0; message = message.substring(1);
}
}
// Receive pv data
while(Wait_485 && (Serial1.available() > 0)) {
c = Serial1.read();
if((c == '\n') && (Buf_485.endsWith("\r"))){
Buf_485.remove(Buf_485.length() - 1); //remove CR
message = Buf_485;
Buf_485 = "";
Wait_485 = false;
Wait_485_cnt = 0;
} }
else{
Buf_485 += c; int ret = sscanf(message.c_str(), "%2s%3s,%2s,%4x,%4x,%4x,%4x,%4x,%4x,%4x,%4x%2x",
addrC, modeC, statusC, &dataC[0], &dataC[1], &dataC[2], &dataC[3], &dataC[4], &dataC[5], &dataC[6], &dataC[7], &crcC);
if (strcmp(statusC, "OK") != 0 || ret != 12) {
return 0;
} }
}
// save pv // copy data
if(message != ""){ addr = atoi(addrC);
for(int i = 0 ; i < size ; i++){ mode = String(modeC);
//arr[i] = ???; for (int i = 0; i < 8; i++) {
data[i] = dataC[i];
} }
} crc = crcC;
return 1;
} }
void write_mc9(int arr[], int size){ String sumMC9(String input) {
digitalWrite(RS485_OE_1, Snd_485); delay(5); int sum = 0;
Serial1.print("485 Write^^\r\n"); //Serial Write ADC_Value to RS-485 Bus for (char c : input) {
Serial1.flush(); sum += c;
digitalWrite(RS485_OE_1, Rcv_485); delay(5); }
sum = sum & 0xFF; // Make sure we only keep the least significant byte
String hexSum = String(sum, HEX); // Convert the sum to hexadecimal
hexSum.toUpperCase(); // Make it upper-case
return hexSum;
} }
*/

@ -1,3 +1,32 @@
String Prcss_DO_Write(unsigned int data[], int dataSize){
String str = "DO!:";
if(dataSize != 1){
str += RcvErr;
return str;
}
unsigned int data0 = data[0];
for (int bit = 0; bit < 16; bit++) {
digitalWrite(DoPin[bit], bitRead(data0, bit) ? HIGH : LOW);
}
str += RcvOK;
return str;
}
String Prcss_DI_Read(){
String str = "DI?:";
//for (int i = 0; i < Size_DI; i++) {
char formattedNumber[5]; // 4자리 숫자 + 널 종료 문자
sprintf(formattedNumber, "%04X", Values_DI); // 4자리로 고정된 형식의 문자열 생성
str += formattedNumber; // 형식화된 문자열 추가
str += ',';
//}
str += RcvOK;
return str;
}
// //
String Prcss_AI_Read(){ String Prcss_AI_Read(){
String str = "AI?:"; String str = "AI?:";
@ -53,12 +82,27 @@ String Prcss_SV_Read(){
String Prcss_SV_Write(unsigned int data[], int dataSize){ String Prcss_SV_Write(unsigned int data[], int dataSize){
String str = "SV!:"; String str = "SV!:";
String message, cmd, cmdData;
cmd = "10DWR,08,";
cmdData = "";
for(int i=0 ; i<dataSize ; i++){ for(int i=0 ; i<dataSize ; i++){
str += String(data[i]); char hexStr[5]; // Buffer to hold the hexadecimal string (4 characters + null terminator)
str += "\t"; sprintf(hexStr, "%04X", data[i]); // Format as 4 digit uppercase hexadecimal
cmdData += MC9_CH[i] + 1; // ZONE 1
cmdData += ",";
cmdData += String(hexStr);
if(i != dataSize -1){
cmdData += ",";
}
} }
//write_buff_first(Buff_485_Wr, String str)
Serial.println(str); message = cmd + cmdData;
message += sumMC9(message);
message = "" + message + CRLF;
write_buff_first(Buff_485_Wr, message);
Serial.println(cmdData);
return RcvOK; return RcvOK;
} }

@ -3,8 +3,6 @@
#define Snd_485 HIGH #define Snd_485 HIGH
#define Rcv_485 LOW #define Rcv_485 LOW
#define MC9_10_PV "10DRS,08,0001CB"
#define MC9_10_SV "10DRS,08,0011CC"
void RS485_setup(){ void RS485_setup(){
Serial1.setTimeout(300); Serial1.setTimeout(300);
@ -16,14 +14,14 @@ void RS485_setup(){
void send_485(){ void send_485(){
if(!Wait_485){ if(!Wait_485){
String message = read_buff(Buff_485_Wr); String message = read_buff(Buff_485_Wr);
// Send request to return pv data
//Serial.println(Buff_485_Wr);
//Serial.print(message);
//Serial.print(" : ");
if(message != ""){ if(message != ""){
//save sent message info. for received data processing
latest_sent_msg = message; latest_sent_msg = message;
message += "\r\n";
message += CRLF;
digitalWrite(RS485_OE_1, Snd_485); delay(5); digitalWrite(RS485_OE_1, Snd_485); delay(5);
Serial1.print(message); Serial1.print(message);
returnTime = millis(); returnTime = millis();
@ -36,12 +34,10 @@ void send_485(){
else{ else{
//Serial.println("Free"); //Serial.println("Free");
} }
} }
} }
int read_485(){ int recieve_485(){
// Timeout code // Timeout code
if(Wait_485){ if(Wait_485){
Wait_485_cnt++; Wait_485_cnt++;
@ -68,55 +64,54 @@ int read_485(){
int data[8]; int data[8];
int crc; int crc;
numOf485--; numOf485--;
//message.replace("\r\n","");
//Serial.println(message);
if (parseMessage(message, addr, mode, data, crc)) {
if(latest_sent_msg == MC9_10_PV){
for(int i = 0 ; i < Size_PV ; i++){ /* To be moved @MC0.ino */
Values_10_PV[i] = data[i]; if((latest_sent_msg == MC9_10_PV) ||(latest_sent_msg == MC9_10_SV)){
if (parseMC9(message, addr, mode, data, crc)) {
if(latest_sent_msg == MC9_10_PV){
for(int i = 0 ; i < Size_PV ; i++){
Values_10_PV[i] = data[i];
}
} }
} if(latest_sent_msg == MC9_10_SV){
if(latest_sent_msg == MC9_10_SV){ for(int i = 0 ; i < Size_SV ; i++){
for(int i = 0 ; i < Size_SV ; i++){ Values_10_SV[i] = data[i];
Values_10_SV[i] = data[i]; }
} }
} else {
Serial.println("error 485 read");
} }
} else {
// OK가 아닌 경우 또는 파싱 오류가 발생한 경우
Serial.println("error 485 read");
} }
else{
Serial.print("485 rcv : ");
Serial.println(message);
}
Wait_485 = false; Wait_485 = false;
Wait_485_cnt = 0; Wait_485_cnt = 0;
} }
return 1; return 1;
} }
int parseMessage(const String& message, int& addr, String& mode, int data[8], int& crc) { /* For Test from PC */
char addrC[3], modeC[4], statusC[3]; void recieve_485_0(){
int dataC[8], crcC;
if (message[0] == '\x02') {
message = message.substring(1);
}
int ret = sscanf(message.c_str(), "%2s%3s,%2s,%4x,%4x,%4x,%4x,%4x,%4x,%4x,%4x%2x",
addrC, modeC, statusC, &dataC[0], &dataC[1], &dataC[2], &dataC[3], &dataC[4], &dataC[5], &dataC[6], &dataC[7], &crcC);
// Receive pv data
while(Serial.available() > 0) {
char c = Serial.read();
IdeSerial += c;
}
if (strcmp(statusC, "OK") != 0 || ret != 12) { if(IdeSerial.endsWith("\n")){
// 오류 처리 IdeSerial.replace(CRLF,"");
return 0; IdeSerial += sumMC9(IdeSerial);
} IdeSerial = "" + IdeSerial + CRLF;
// 복사 write_buff_first(Buff_485_Wr, IdeSerial);
addr = atoi(addrC); IdeSerial = "";
mode = String(modeC); }
for (int i = 0; i < 8; i++) {
data[i] = dataC[i];
}
crc = crcC;
return 1;
} }

@ -12,6 +12,11 @@ int write_buff_c(char* buff, char c) {
int write_buff(char* buff, String str) { int write_buff(char* buff, String str) {
// check if last characters are not CRLF and append if not
if (!str.endsWith(CRLF)) {
str += CRLF;
}
const char* cstr = str.c_str(); const char* cstr = str.c_str();
size_t len = strlen(cstr); size_t len = strlen(cstr);
if (strlen(buff) + len < BUFF_SIZE) { if (strlen(buff) + len < BUFF_SIZE) {
@ -24,6 +29,7 @@ int write_buff(char* buff, String str) {
} }
} }
int write_buff_first(char* buff, String str) { int write_buff_first(char* buff, String str) {
const char* cstr = str.c_str(); const char* cstr = str.c_str();
size_t len = strlen(cstr); size_t len = strlen(cstr);
@ -40,12 +46,14 @@ int write_buff_first(char* buff, String str) {
} }
} }
String read_buff(char* buff) { String read_buff(char* buff) {
char* pos = strstr(buff, "\r\n"); char* pos = strstr(buff, CRLF);
String output = ""; String output = "";
if (pos != nullptr) { if (pos != nullptr) {
size_t len = pos - buff; size_t len = pos - buff;
output = String(buff).substring(0, len); output = String(buff).substring(0, len);
//output += CRLF;
// Shift remaining string to the start // Shift remaining string to the start
memmove(buff, pos + 2, strlen(pos + 2) + 1); memmove(buff, pos + 2, strlen(pos + 2) + 1);

@ -1,16 +1,16 @@
//
void Periodic_run(){ void Periodic_run(){
if(T_10ms){ if(T_10ms){
read_analog();
T_10ms = false; T_10ms = false;
} }
if(T_20ms){ if(T_20ms){
read_485(); send_485(); // RS485 send
send_485(); recieve_485(); // RS485 recieve
T_20ms = false; T_20ms = false;
} }
if(T_50ms){ if(T_50ms){
read_analog();
read_digital();
T_50ms = false; T_50ms = false;
} }
if(T_100ms){ if(T_100ms){
@ -22,6 +22,7 @@ void Periodic_run(){
T_200ms = false; T_200ms = false;
} }
if(T_500ms){ if(T_500ms){
recieve_485_0(); // RS485 recieve (for developing)
T_500ms = false; T_500ms = false;
} }
if(T_1000ms){ if(T_1000ms){
@ -29,8 +30,8 @@ void Periodic_run(){
T_1000ms = false; T_1000ms = false;
} }
if(T_2000ms){ if(T_2000ms){
Serial.print("----- remain 485 buff : "); Serial.print("----- remain 485 buff : "); // For
Serial.println(numOf485); Serial.println(numOf485); // Debugging
T_2000ms = false; T_2000ms = false;
} }
if(T_5000ms){ if(T_5000ms){
@ -67,5 +68,4 @@ void timer_10ms(){
T_5000ms = true; T_5000ms = true;
msCnt = 0; msCnt = 0;
} }
} }

Loading…
Cancel
Save