PDA

Просмотр полной версии : Вопрос по Ардуино. Хелп плиз-((


CyberSubaru
12.07.2010, 14:27
Плата: фридуино на 168й меге.
Пишу программку общения с ком-портом.
Суть - в порт передаются команды типа ATS12345
Программка их парсит побайтно и в зависимости от команды выполняет те или иные действия.

Уперся я о непонятный камень:
код работает нестабильно.

в монитор порта вбиваю ATS
в 50% случаев (примерно)
код доходит до выполнения Serial.println("SET COMMAND /PIN ");
НО(!!!!)
Стабильно в цикле забивания массива выводит именно те байты, что передавались. Но if и switch работают по-китайски.

И еще нюанс такой: Serial.print как-то больше способствует корректной работе кода с массивом.

В чем может быть трабл? Уже идей никаких нет.


void setup()
{
Serial.begin(115200);
// Serial.println("ECU READY");
}


int cmd[64];
int i;
int pin;
int maxdata;

void loop()
{

maxdata=0;

for(i=0;i<64;i++) {cmd[i]=0;}

i=0;

while (Serial.available()>0)
{
cmd[i]=Serial.read();
Serial.print(cmd[i],BYTE);
i++;
maxdata++;
}


if ((cmd[0]==65)and(cmd[1]==84))
{
// Serial.println("AT OK");

switch (cmd[2])
{
case 73: { //'I'

};
break;

case 71: { //'G'
pin=cmd[3];
};
break;

case 83: { //'S'
Serial.println("SET COMMAND /PIN ");
pin=cmd[3];
// Serial.println(pin,BYTE);
// Serial.println(cmd[4],BYTE);


switch (cmd[4])
{
case 1: pinMode(pin, INPUT); break;
case 2: pinMode(pin, OUTPUT); break;
case 3: digitalWrite(pin,cmd[5]);break;
case 4: analogWrite(pin,cmd[5]);break;
}

};
break;
}
}


}

ancc
12.07.2010, 14:49
ваще seral.println Никогда не использовал. только serial.print.

и еще. массив cmd[i] очищается если ни одно из условий не выполняется или нет?

может жестко проверять при приеме данных из порта по маске команды и как только расхождение обнаружилось сразу массив очищать.

ancc
12.07.2010, 14:59
и еще. про serial.flush после каждого приема верной комманды не помешает вроде. Хотя тут я хз. вроде не надо.

CyberSubaru
12.07.2010, 15:11
ваще seral.println Никогда не использовал. только serial.print.

и еще. массив cmd[i] очищается если ни одно из условий не выполняется или нет?

может жестко проверять при приеме данных из порта по маске команды и как только расхождение обнаружилось сразу массив очищать.
да пока только что и вбиваю одно и тоже - ATS
так что обработка ИНАЧЕ смысла пока не имеет.
вот результат нескольких подряд вбитых "ATS1234":

AT

AT OK
S1234AT

AT OK
S1234AT

AT OK
S1234ATS1234ATS

AT OK
SET COMMAND /PIN


1234ATS

AT OK
SET COMMAND /PIN


1234ATS1234ATS1234ATS

AT OK
SET COMMAND /PIN


1234

добавил перевод каретки

и еще. про serial.flush после каждого приема верной комманды не помешает вроде. Хотя тут я хз. вроде не надо.
с ним вообще работает криво....

ancc
12.07.2010, 15:26
выберете жестко формат комманды AT xxxxx <cr>
и по этой маске команды парсите. как только у вас расхождение команды с маской буфер очищаете и ничего в него не пишете пока первый символ "A" не появится. С этого момента начинаете писать в буфер и снова сличать с маской.

CyberSubaru
12.07.2010, 15:34
выберете жестко формат комманды AT xxxxx <cr>
и по этой маске команды парсите. как только у вас расхождение команды с маской буфер очищаете и ничего в него не пишете пока первый символ "A" не появится. С этого момента начинаете писать в буфер и снова сличать с маской.

Читайте, пожалуйста, внимательнее!
вот результат нескольких подряд вбитых "ATS1234"
Команды вбиваю в монитор порта (в ардуино который) - одну и туже.
Результат работы кода - разный.
Код элементарный - читаем байты с порта, пока есть данные, забиваем их в массив и далее смотрим, если первые два AT, то смотрим дальше. Вот это условие при одинаковых входных данных срабатывает не всегда. И Switch-case тоже срабатывает не всегда, при одинаковых входных данных.
Вопрос - почему такое может быть?

ancc
12.07.2010, 15:38
а что мешает вам добавить немного обратной связи? выводите ваш буфер обратно (с целью отладки), будете знать что там у вас лежит.

и я бы посоветовал комманду заканчивать <cr> (ентер грубо говоря).

CyberSubaru
12.07.2010, 15:41
а что мешает вам добавить немного обратной связи? выводите ваш буфер обратно (с целью отладки), будете знать что там у вас лежит.

и я бы посоветовал комманду заканчивать <cr> (ентер грубо говоря).

Вы код программы читали? Складывается такое впечатление, что вместо помощи, Вы издеваетесь.

ancc
12.07.2010, 15:53
да и не думал вообще-то. Подскажите вот у вас в программе:

((cmd[0]==65)and(cmd[1]==84))

я правильно понимаю что начало команды вы хотите увидеть обязательно в первом элементе массива?

CyberSubaru
12.07.2010, 16:01
да и не думал вообще-то. Подскажите вот у вас в программе:

((cmd[0]==65)and(cmd[1]==84))

я правильно понимаю что начало команды вы хотите увидеть обязательно в первом элементе массива?

верно.
потому что это и предполагается.
вот когда это условие срабатывает - необязательно срабатывает следующее условие проверки элементов массива, будто он где-то повреждается.

ancc
12.07.2010, 16:03
так если в массив за раз попадет несколько ваших команд которые вы печатаете последовательно, вторая разве будет работать?

CyberSubaru
12.07.2010, 16:07
КОРКА.
добавил вывод счетчика главных циклов.
РАБОТАЕТ КАК ШВЕЙЦАРСКИЕ ЧАСЫ.

ввожу ATSQWERTY

код
int loopc;
void setup()
{
Serial.begin(115200);
// Serial.println("ECU READY");
loopc=0;
}


int cmd[64];
int i;
int pin;
int maxdata;




void loop()
{

maxdata=0;
loopc++;

for(i=0;i<64;i++) {cmd[i]=0;}

i=0;

while (Serial.available()>0)
{
cmd[i]=Serial.read();
Serial.print(cmd[i],BYTE);
Serial.print(loopc,DEC);
i++;
maxdata++;
}
// Serial.flush();

if ((cmd[0]==65)and(cmd[1]==84))
{
Serial.println("\r\n");
Serial.println("AT OK");

switch (cmd[2])
{
case 73: { //'I'

};
break;

case 71: { //'G'
pin=cmd[3];
};
break;

case 83: { //'S'
Serial.println("SET COMMAND /PIN ");
pin=cmd[3];
// Serial.println(pin,BYTE);
// Serial.println(cmd[4],BYTE);


switch (cmd[4])
{
case 1: pinMode(pin, INPUT); break;
case 2: pinMode(pin, OUTPUT); break;
case 3: digitalWrite(pin,cmd[5]);break;
case 4: analogWrite(pin,cmd[5]);break;
};

Serial.println("\r\n");

};
break;
}

}


}

результат

A-9008T-9008S-9008Q-9008W-9008E-9008R-9008T-9008Y-9008

AT OK
SET COMMAND /PIN


A23933T23933S23933Q23933W23933E23933R23933T23933Y2 3933

AT OK
SET COMMAND /PIN


A-26026T-26026S-26026Q-26026W-26026E-26026R-26026T-26026Y-26026

AT OK
SET COMMAND /PIN


A-11042T-11042S-11042Q-11042W-11042E-11042R-11042T-11042Y-11042

AT OK
SET COMMAND /PIN


A3653T3653S3653Q3653W3653E3653R3653T3653Y3653

AT OK
SET COMMAND /PIN


A17269T17269S17269Q17269W17269E17269R17269T17269Y1 7269

AT OK
SET COMMAND /PIN


A32459T32459S32459Q32459W32459E32459R32459T32459Y3 2459

AT OK
SET COMMAND /PIN




ЕЩЕ БОЛЬШЕ КОРКА

ЗАКОМЕНТИЛ
// Serial.print(loopc,DEC);

РЕЗУЛЬТАТ ИСПОРТИЛСЯ
ATSQWERTYAT

AT OK
SQWERTYATSQWERTYATS

AT OK
SET COMMAND /PIN


QWERTYAT

AT OK
SQWERTYATSQWERTYAT

AT OK
SQWERTYAT

AT OK
SQWERTY

CyberSubaru
12.07.2010, 16:11
так если в массив за раз попадет несколько ваших команд которые вы печатаете последовательно, вторая разве будет работать?

на данный момент в массиве только одна команда.
он каждый раз перед чтением порта обнуляется.

CyberSubaru
12.07.2010, 17:48
Вот вывод массива с номерами элементов
номер через слэш

A/0T/1S/2Q/3W/4E/5R/6T/7Y/8

AT OK
SET COMMAND /PIN


A/0T/1S/2Q/3W/4E/5R/6T/7Y/8

AT OK
SET COMMAND /PIN


A/0T/1S/2Q/3W/4E/5R/6T/7Y/8

AT OK
SET COMMAND /PIN


A/0T/1S/2Q/3W/4E/5R/6T/7Y/8

AT OK
SET COMMAND /PIN


A/0T/1S/2Q/3W/4E/5R/6T/7Y/8

AT OK
SET COMMAND /PIN

CyberSubaru
12.07.2010, 18:51
проблема решилась заменой Serial.print() на delay(1);
во как!
точнее обошел проблему))