BASIC4MCU | 질문게시판 | 아두이노 시리얼 통신 버퍼링 이슈
페이지 정보
작성자 엔야 작성일2023-02-02 14:06 조회149회 댓글0건
https://www.basic4mcu.com/bbs/board.php?bo_table=gac&wr_id=22294
본문
안녕하세요.
프로젝트를 진행함에 있어 아두이노 우노를 이용하고 있습니다.
사용 중인 센서가 RS485 통신을 이용하여 요청 값을 수신받으면 해당 값을 송신해주는 형태로 아두이노 우노에는 RS485 통신 기능이 없기에 중간에 MAX485 모듈을 사용하고 있습니다.
이 통신하여 받은 값은 리틀 엔디안으로 다시 계산하여, 값을 I2C를 통해 DAC 값으로 별도의 디스플레이로 보내서 그래프를 띄우고 있는데,
그래프가 중간중간 끊기는 현상이 있어 I2C 로 전달되기 전 값을 확인해보니 중간중간 아두이노 우노가 버퍼링이 걸린 것처럼 멈추는 현상이 일어나고 있습니다.
혹시 해당 부분을 개선할 수 있는 방법이 있을까요?
시리얼 버퍼에 대한 문제일 것 같기도 하는데 두 달 넘게 고민하고 이런저런 시도를 해봤으나 더 이상 해결할 방법이 생각이 나지 않아 이렇게 질문 게시판에 작성합니다.
도움을 부탁드립니다.
[버퍼링 걸린 것처럼 값 수신이 일시 정지 되는 현상]
감사합니다.
현재 작성 코딩
//Flow Sensor
- #include
- #include
- #include
- Adafruit_MCP4725 dac;
- // Pin 선언
- #define modepin 3 // RS 485 통신의 송신과 수신을 변환하는 핀
- #define readmode LOW
- #define sendmode HIGH
- SoftwareSerial rs485(4, 2); // RS 485 RX, TX
- const int readMax = 1; // 임시 추가_나누기 값
- long double readings[readMax]; // 임시 추가
- unsigned int readIndex = 0;
- unsigned int total = 0;
- unsigned int avg = 0;
- //통신 세팅
- void setup() {
- rs485.begin(115200); //아두이노-rs485간 TTL통신
- //Serial.begin(9600); //PC-아두이노간 TTL통신
- pinMode(modepin,OUTPUT); //송수신제어핀
- digitalWrite(modepin,readmode); //수신모드
- dac.begin(0x60); //DAC 변환
- }
- //작동
- void loop() {
- byte request[] = {0xF1,0x00,0x0B,0x3F,0x0B,0x00,0x8A,0x82,0x8B,0x2A,0x38}; // Flow Sensor에게 주는 명령값
- //RS485 송신모드로 변경
- digitalWrite(modepin,sendmode);
- //데이터 전송
- rs485.write(request,11);
- //다시 수신모드로 변경
- digitalWrite(modepin,readmode);
- //센서의 응답을 기다려야 하는 상태
- byte response[23]= {0};
- if(rs485_receive(response) != -1){
- for(int i = 0;i<23;i++){
- response[i];
- }
- delay(100);
- double flowvalue = 0;
- unsigned int flowcasting = 0;
- unsigned int flowconversion = 0;
- unsigned int flowAnalog = 0;
- unsigned int bubblevlaue =0;
- //flow 값 IEEE754 및 리틀 엔디안 적용
- ((byte*)&flowvalue)[3]= response[11];
- ((byte*)&flowvalue)[2]= response[10];
- ((byte*)&flowvalue)[1]= response[9];
- ((byte*)&flowvalue)[0]= response[8];
- if(flowvalue <= 0){
- flowcasting = 0;
- }
- else if(flowvalue >= 10000){
- flowcasting = 10000;
- }
- else{
- flowcasting = (int)flowvalue; //값을 정수형태로 변환
- }
- flowconversion = flowcasting/10; // 값이 변수 용량을 넘을 수 있으니 일단 10으로 나눠서 낮춤
- // 필터링을 위한 값 평균 구하기(현재는 readMax를 1로 하기 때문에 큰 의미X)
- total = total - readings[readIndex];
- readings[readIndex] = flowconversion;
- total = total + readings[readIndex];
- if(total <= 0){
- total = 0;
- }
- readIndex = readIndex + 1;
- if (readIndex >= readMax) {
- readIndex = 0;
- }
- avg = (total / readMax)*10;
- // 여기까지
- //유량 값 아날로그 출력값 지정
- flowAnalog = avg *0.4095;
- if(flowAnalog > 4095)
- {
- dac.setVoltage(4095, false);
- delay(50);
- }else if(0 <= flowAnalog <= 4095)
- {
- dac.setVoltage(flowAnalog, false);
- delay(50);
- }else if(flowAnalog < 0){
- dac.setVoltage(0, false);
- delay(50);
- }
- Serial.println(flowAnalog);
- response[23] = {0};
- flowvalue = 0;
- }
- }
- int rs485_receive(byte recv[]){
- //슬레이브1에서 날린 데이터가 존재할 때까지 무한루프
- unsigned long t = millis(); //루프 진입 직전의 시간
- while(1){
- if(millis() - t > 2000){
- return -1;
- break;
- }
- if(rs485.available()){
- //485모듈에서 아두이노쪽으로 수신한값이 존재하는 경우
- //데이터 읽기
- rs485.readBytes(recv,23);
- return 0;
- break;
- }
- }
- }
댓글 0
조회수 149등록된 댓글이 없습니다.