Проблемы государственной машины

У меня проблема с настройкой конечного автомата. Я знаю это, поэтому у меня возникла проблема. Так что здесь есть несколько методов, которые можно игнорировать. Основная проблема в том, что по какой-то причине он отправляет сообщение для каждого полученного байта, но я думал, что Serial.read () очищает буфер после чтения.
Итак, вот основная часть кода:

#include "Arduino_Structures.h"#include <SPI.h>
#include <Ethernet.h>
#include "Time.h"
//GLOBAL DECLARATIONS
enum { STANDBY, SEND, RECEIVE, PROCESS} state = SEND;
enum { STATUS, CONFIG, CURRENT, TIME, VOLTAGE} messageType = STATUS;

char lcv;
char lcv2; //loop control variables

MESSAGE_STRUCT outgoing;    //changing outgoing message
MESSAGE_STRUCT incoming;    //changing incoming message
OODLES_BLOCK oodles;            //oodles of information from the following  5 blocks
STATUS_BLOCK temp_status;       //temporary status block
CONFIG_BLOCK temp_config;       //temporary config block
CURRENT_BLOCK temp_current; //temporary current block
TIME_BLOCK temp_time;               //temporary time block
VOLTAGE_BLOCK temp_voltage; //temporary voltage block//FUNCATION DECLARATIONS
void sendMsg(MESSAGE_STRUCT* outgoing);
void receiveMsg(MESSAGE_STRUCT* incoming);

//ARDUINO SETUP
void setup()
{
delay(TIMEOUT); //wait for the boards to start up
Serial.begin(BAUD); //set the arduino to be at the Micro-AT baud rate
do
{
lcv = Ethernet.begin(mac); //start etherent board, get IP
}while(!lcv);

}

//ARDUINO LOOP
void loop()
{
switch(state)
{
case STANDBY:
delay(1000);
state = SEND;
break;

case SEND:

switch(messageType)
{
case STATUS:
outgoing.start_byte = 0x00;
outgoing.length = 0x00;
outgoing.address_1 = 0xFF;
outgoing.address_2 = 0xFF;
outgoing.code_word = REQUEST_STATUS;
outgoing.checksum = 0;

sendMsg(&outgoing);
state = RECEIVE;
break;

case CONFIG:
outgoing.start_byte = 0x00;
outgoing.length = 0x00;
outgoing.address_1 = 0xFF;
outgoing.address_2 = 0xFF;
outgoing.code_word = REQUEST_CONFIG;
outgoing.checksum = 0;

sendMsg(&outgoing);
state = RECEIVE;
break;

case CURRENT:
outgoing.start_byte = 0x00;
outgoing.length = 0x00;
outgoing.address_1 = 0xFF;
outgoing.address_2 = 0xFF;
outgoing.code_word = REQUEST_CURRENT;
outgoing.checksum = 0;

sendMsg(&outgoing);
state = RECEIVE;
break;

case TIME:
outgoing.start_byte = 0x00;
outgoing.length = 0x00;
outgoing.address_1 = 0xFF;
outgoing.address_2 = 0xFF;
outgoing.code_word = REQUEST_TIME;
outgoing.checksum = 0;

sendMsg(&outgoing);
state = RECEIVE;
break;

case VOLTAGE:
outgoing.start_byte = 0x00;
outgoing.length = 0x00;
outgoing.address_1 = 0xFF;
outgoing.address_2 = 0xFF;
outgoing.code_word = REQUEST_VOLTAGE;
outgoing.checksum = 0;

sendMsg(&outgoing);
state = RECEIVE;
break;

default:
break;
}
break;
case RECEIVE:
if(Serial.available())
{
state = SEND;
receiveMsg(&incoming);
//NEED TO CHECK TO MAKE SURRE START BYTE AND ADDRESS ARE CORRECT
//ALSO THIS IS WHERE I SHOULD CHECK THE CHECKSUM
//ONCE INSIDE SWITCHES NEED TO MAKE SURE THE RESPONSE IS CORRECT
switch(messageType)
{
case STATUS:
//copy information from incoming's data array to the temp_status block so that it retains its structure
memcpy(&temp_status, &incoming.data, sizeof(STATUS_BLOCK));

//these are directly taken from the status block information (Arduino_Structures.h)
oodles.left_source = temp_status.left_source;
oodles.right_source = temp_status.right_source;
oodles.left_overcurrent = temp_status.left_overcurrent;
oodles.right_overcurrent = temp_status.right_overcurrent;
oodles.automatic_transfer = temp_status.ready;
oodles.event_led = temp_status.event;
oodles.bus_type = temp_status.bus_type;
oodles.preferred = temp_status.preferred;
oodles.lockout_installed = temp_status.lockout_installed;
oodles.supervisory_control = temp_status.supervisory_control;

//put the time into the TimeElement then convert it to unix time
TimeElements timeInfo; //will be used (from Time.h library)
timeInfo.Year = temp_status.year;
timeInfo.Month = temp_status.month;
timeInfo.Day = temp_status.day;
timeInfo.Hour = temp_status.hour;
timeInfo.Minute = temp_status.minute;
timeInfo.Second = temp_status.second;
oodles.unix_time = makeTime(timeInfo);

//might want to wipe incoming and outogoing messages to make sure they get correctly rewritten
//messageType = CONFIG;
//state = SEND;
break;

case CONFIG:
break;

case CURRENT:
break;

case TIME:
break;

case VOLTAGE:
break;
}
}
break;

case PROCESS:
break;
}
}

void sendMsg(MESSAGE_STRUCT* message)
{
//brake up integers from MESSAGE_STRUCT to bytes (see intByte in Arduino_Structures.h)

intByte code_word, checksum;

code_word.intValue = message->code_word;
checksum.intValue = message->checksum;

//send byte by byte
Serial.write(message->start_byte);
Serial.write(message->length);
Serial.write(message->address_1);
Serial.write(message->address_2);
Serial.write(code_word.byte1);
Serial.write(code_word.byte2);

for(lcv = 0; lcv < message->length; lcv++)
Serial.write(message->data[lcv]);

Serial.write(checksum.byte1);
Serial.write(checksum.byte2);
}

void receiveMsg(MESSAGE_STRUCT* message)
{
//receive bytes and put them back as integers (see intByte in Arduino_Structures.h)
intByte code_word, checksum;

//receive byte by byte
message->start_byte = Serial.read();
message->length = Serial.read();
message->address_1 = Serial.read();
message->address_2 = Serial.read();
code_word.byte1 = Serial.read();
code_word.byte2 = Serial.read();
message->code_word = code_word.intValue;

for(lcv = 0; lcv < message->length; lcv++)
message->data[lcv] = Serial.read();

checksum.byte1 = Serial.read();
checksum.byte2 = Serial.read();
message->checksum = checksum.intValue;
}

А вот последовательный монитор, показывающий ошибку, он должен ответить только один раз, и если я отправлю ему только один байт, он ответит один раз. Если я отправлю ему 8-байтовый ответ, как показано ниже, он ответит 8 раз («Ответить» означает arduino на ноутбук, а «запрос» означает ноутбук на arduino):

Answer: 6/26/2013 4:30:59 PM.56364 (+11.3133 seconds)

00 00 FF FF 00 01 00 00

Request: 6/26/2013 4:31:00 PM.48564 (+0.9219 seconds)

00 00 FF FF 01 01 00 00

Answer: 6/26/2013 4:31:00 PM.51664 (+0.0156 seconds)

00 00 FF FF 00 01 00 00 00 00 FF FF 00 01 00 00
00 00 FF FF 00 01 00 00 00 00 FF FF 00 01 00 00
00 00 FF FF 00 01 00 00 00 00 FF FF 00 01 00 00
00 00 FF FF 00 01 00 00 00 00 FF FF 00 01 00 00

0

Решение

Похоже, вы проверяете, чтобы увидеть, что Serial.available() не ноль, а затем читать кучу данных. Возможно, вы не закончили получать данные, когда начинаете receiveMsg функция. Вам следует:

  1. Убедитесь, что нужные вам байты доступны. Подождите, если
  2. Они недоступны, но вы ожидаете, что они скоро придут

Просто в качестве примера:

void receiveMsg(MESSAGE_STRUCT* message)
{
// receive bytes and put them back as integers
intByte code_word, checksum;

// receive byte by byte, wait for it if need be
while( Serial.available() < 1 ) {delay(10);}
message->start_byte = Serial.read();
while( Serial.available() < 1 ) {delay(10);}
message->length = Serial.read();

Есть лучшие, более надежные способы сделать это, но это довольно просто и легко реализуется для теста, чтобы увидеть, не заполнен ли входной буфер.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]