BASIC4MCU | 질문게시판 | 앱인벤터 list index too large 오류 질문입니다. 도와주세요ㅜㅜ
페이지 정보
작성자 PT규 작성일2022-07-07 19:58 조회63,361회 댓글11건본문
안녕하세요 우선 글 읽어주셔서 감사합니다.
아두이노로 블루투스를 통해 앱으로 통신을 하고 있는데 시리얼 통신과 블루투스 터미널을 통해
데이터가 STX data ETX 형태로 꾸준히 들어오는 것을 확인한 뒤
앱인벤터로 구성을 해봤는데요
데이터 값이 변화하니 list index too large 라는 오류가 발생하네요..
데이터 개수는 66개가 항상 동일하게 들어오는데 데이터 값이 변화할때
리스트개수가 항목보다 적다고 합니다..
항목가져오기 리스트 블럭에서 위치는 STX~ data ~ ETX까지 1~66까지 설정해두었습니다.
이런 경우 어떻게 해결해야할까요??
댓글 11
조회수 63,361master님의 댓글
master 작성일
PC나 휴대폰의 경우 OS레벨에서 시리얼데이터 1바이트마다 처리하지 않고 몰아서 처리합니다.
64개의 항목을 모두 받은 후에 이벤트를 발생하면 좋지만
언제 끝날지 알 수 없는 상태에서 적당한(?) 시기에 이벤트를 날려주는데
데이터 도중에 이벤트를 날리게 되면서 위와 같은 현상이 발생합니다.
master님의 댓글
master 작성일
115200로 보레이트를 높이고
999 출력 후에 딜레이를 충분히 줘보세요(1초 딜레이)
//
PC프로그램에서 데이트를 수신해서 이전에 모았던 것과 취합하고(더해주고)
시작문자부터 종료 문자까지 다 받았다면 처리하고, 남은 것은 다음에 받을 데이터와 취합하기 위해서 남겨둡니다.
이런식으로 처리해야 하는데, 앱인벤터 등에서 그런 복잡한 처리까지 고려해서 만들었을 것으로는 보이지 않습니다.
PT규님의 댓글
PT규
답변 감사합니다
오류난 원인에 대해 무엇이 문제인지는 답변을 통해 이해를 했습니다
압력센서에서 실시간으로 데이터를 넘기는 과정에서 오류가 난거 같은데..
시작문자부터 종료 문자까지 다 받았다면 처리하고, 남은 것은 다음에 받을 데이터와 취합하기 위해서 남겨둡니다. -> 여기서의 처리 과정을 어떻게 해야할지가 고민이네요..
지금은 loop문 안에서 Serial.print를 이용해 데이터를 출력하고 loop문이 끝나는 곳에서 Serial.println으로 데이터를 모아서 보내고 있었는데 다른 방식으로 데이터를 전달해야할지
아니면 앱인벤터 상에서 수신받는 데이터 처리를 바꿔야할지도 고민이고.. 방법도 잘 안나오네요.. 혹시 참고할만한게 있으면 알려주시면 감사하겠습니다!
master님의 댓글
master
아두이노 전체 소스 첨부 해보세요
보레이트는 변경 했나요?
PT규님의 댓글
PT규
#include<SoftwareSerial.h>
SoftwareSerial btserial(2, 3);
unsigned long t = 0;
const byte s0 = 7;
const byte s1 = 8;
const byte s2 = 9;
const byte w0 = 2;
const byte w1 = 3;
const byte w2 = 4;
const byte SIG_pin = A0;
const byte OUT_pin = 12;
const boolean muxChannel[8][3]={
{0,0,0}, //channel 0
{1,0,0}, //channel 1
{0,1,0}, //channel 2
{1,1,0}, //channel 3
{0,0,1}, //channel 4
{1,0,1}, //channel 5
{0,1,1}, //channel 6
{1,1,1} //channel 7
};
int inByte = 0;
int valor = 0;
int calibra[8][8];
int minsensor=254;
int multiplier = 254;
int pastmatrix[8][8];
void setup(){
pinMode(s0, OUTPUT);
pinMode(s1, OUTPUT);
pinMode(s2, OUTPUT);
pinMode(w0, OUTPUT);
pinMode(w1, OUTPUT);
pinMode(w2, OUTPUT);
pinMode(OUT_pin, OUTPUT);
digitalWrite(s0, HIGH);
digitalWrite(s1, HIGH);
digitalWrite(s2, HIGH);
digitalWrite(w0, HIGH);
digitalWrite(w1, HIGH);
digitalWrite(w2, HIGH);
digitalWrite(OUT_pin, HIGH);
Serial.begin(115200);
btserial.begin(115200);
}
void loop(){
if(btserial.available() > 0)
{
if(millis() - t > 100)
{
t = millis();
btserial.print(888); // STX
btserial.print(","); // split
for(int j = 0; j < 8; j++)
{
writeMux(j);
for(int i = 0; i < 8; i++)
{
valor = calibra[j][i];
btserial.print(valor); // data
btserial.print(","); // split
}
}
}
btserial.println(999); // ETX
}
}
int readMux(byte channel){
byte controlPin[] = {s0, s1, s2};
//loop through the 4 sig
for(int i = 0; i < 3; i ++){
digitalWrite(controlPin[i], muxChannel[channel][i]);
}
//read the value at the SIG pin
int val = analogRead(SIG_pin);
//return the value
return val;
}
void writeMux(byte channel){
byte controlPin[] = {w0, w1, w2};
//loop through the 4 sig
for(byte i = 0; i < 3; i ++){
digitalWrite(controlPin[i], muxChannel[channel][i]);
}
}
소스코드 첨부해드립니다.
millis를 1000까지도 해봤지만 센서를 가만히 뒀을때는 딜레이가 짧아도 에러가 거의 안뜨지만
압력을 주어서 센서값을 변화시키면 오류가 발생하는 것을 보니 말씀하신대로 데이터를 넘기는 과정에서 이벤트가 들어가 문제가 생긴것 같긴합니다..
보트레이트는 원래 115200 이었습니다!
master님의 댓글
master
void loop(){
if(btserial.available() > 0){
if(millis() - t > 100){ t = millis();
btserial.print(888); // STX
btserial.print(","); // split
for(int j = 0; j < 8; j++){
writeMux(j);
for(int i = 0; i < 8; i++){
valor = calibra[j][i];
btserial.print(valor); // data
btserial.print(","); // split
}
}
btserial.println(999); // ETX
delay(200);
}
}
}
999 전송하는 위치가 잘 못 되어 있었습니다.
PT규님의 댓글
PT규
위치를 바꿔도 같은 증상이 나옵니다 ㅜㅜ
혹시 몰라 플레이스토어에있는 블루투스 통신 어플로 테스트 해봤는데 STX data ETX 포함 66바이트 나오는건 확인했습니다!
master님의 댓글
master 작성일
중간의 데이터가 문자(열)형식이므로
시작문자와 종료문자는 문자형식을 사용하지 않는 것이 좋습니다.
0x02, 0x03 이런식으로 1바이트 정수데이터를 사용하면 처리하기 좋죠
시작문자와 종료문자를 지정하는 정도는 앱인벤터에도 있을지 모르니 웹검색으로 찾아보세요
master님의 댓글
master 작성일
btserial.print(888); // STX // 3바이트
btserial.print(","); // split // 1바이트
//64*n
btserial.print(valor); // data // 64바이트+a
btserial.print(","); // split // 64바이트
btserial.println(999); // ETX // 3바이트
//
valor가 0~9까지로 1바이트를 전송 한다고 하더라도
135바이트가 전송 됩니다.
만약 valor가 모두 (십진으로)3자리값이라면 263바이트가 됩니다.
master님의 댓글
master 작성일
몇바이트 안되고, 전송 후에 딜레이를 충분히 준다면 PC에서 한꺼번에 전송 할 가능성이 높습니다.
//
그 외에는 20 바이트 수신하고 이벤트를 주기도 하고
수백바이트 수신하고 이벤트를 주기도 합니다.
이벤트는 앱이 아닌 OS 레벨에서 제어하는 것이므로 앱에서 할 수 있는 것이 없습니다.
첫 댓글에 적어드린 것처럼 앱에서 이벤트가 발생 할 때마다 버퍼에 더해나가면서 STX,ETX를 체크해서 버퍼에서 빼 쓰는 수 밖에 없는데요
앱인벤터에서 이런 처리를 해줄 것으로 생각되지는 않습니다.
PT규님의 댓글
PT규
이벤트를 전송하는 부분이 앱인벤터에서 한계가 있군요..
아두이노 상에서 이것저것 더 만져보고 안되면 앱인벤터에서 다른 프로그램으로 바꿔야겠네요..
좋은 조언 해주셔서 정말 감사합니다!