Всем доброго времени суток! Обращаюсь за помощью к знатокам, ибо собственных знаний и сил уже не хватает В общем, задача стоит следующая: необходимо имитировать замок-крутилку (типа, как на сейфе) для решения задачи открытия саркофага. Накрутили верную комбинацию - саркофаг открылся. Данный замок должен передавать этапы прохождения комбинации по локальной сети (три направо, два налево, один направо и т.д. Первый этап - это, например, три круга направо). Устроено сие чудо следующим образом: Arduino Mega 2560 + Ethernet Shield w5100 + механический энкодер (самый простой, китайский) + 2 цифровых датчика холла SS411A. Механический энкодер служит лишь для обновления метки времени, пока никто не крутит крутилку, этап прохождения комбинации сбрасывается. А два датчика холла как раз уже и решают задачу крутилки, определяют направление вращения и количество оборотов. Изначально был сделан прототип на жестком диске (практически такой же, как в статье, за исключением того, что стоит еще механический энкодер). Алгоритм был доработан, для исключения фальш кругов. Т.е. на прототипе все отлично работает и никаких нареканий к устройству нет. Теперь сама проблема: как только ставим данную систему энкодера в купе с Ethernet Shield, то стабильность работы устройства теряется. НО! (самое интересно), при подключении к Arduino по монитору порта - начинает стабильно работать. Подключение показано на картинке во вложении, только в реале датчики холла питаются через понижающий DC DС преобразователь 12v (c комп. БП) -> 5v. Arduino Mega питается через тот же компьютерный блок на вход 5v (блок выдает 5.36v). Код: Код (C++): #include <String.h> #include <SPI.h> #include <Ethernet.h> #include <Encoder.h> #define ENCODER_OPTIMIZE_INTERRUPTS uint8_t prev_state = 0; const uint8_t FORWARD_SEQ = 0b10000111, BACKWARD_SEQ = 0b10110100; uint8_t current_seq = 0; long lastPosition, encPosition, oldencPosition; unsigned int llCount = 0, // переменные кругов влево и вправо lrCount = 0; unsigned long time_current=millis(), // метки времени enc_time = time_current; int stage = 0; // этап прохождения комбинации (всего 5 этапов) #define ENC_PIN1 (18) #define ENC_PIN2 (19) Encoder myEnc(20, 21); byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEA }; IPAddress ip(192,168,0,3); EthernetServer server(80); void setup(){ Serial.begin(9600); pinMode(ENC_PIN1, INPUT); pinMode(ENC_PIN2, INPUT); Ethernet.begin(mac, ip); server.begin(); } void loop() { String req; char c; EthernetClient client = server.available(); if (client) { boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { // начало работы клиента char c = client.read(); req+=c; if (c == '\n' && currentLineIsBlank) { // if (req.indexOf("?")>-1) Serial.println(req.substring(6,req.indexOf(" HTTP"))); // поиск команд // ----------------------------------------------------------------------------------------- // Serial.println(req); // DEBUG: Dump HTTP data client.println("HTTP/1.1 200 OK"); // заголовок client.println("Content-Type: application/json"); client.println("Access-Control-Allow-Origin: *"); client.println("Connection: close"); client.println(); // вывод состояния if(req.indexOf("showstate")>-1){ client.print("{"); client.print("\",\"enc\":\""); // крутилка на саркофаге client.print(stage); client.print("\""); client.println("}"); // end JSON } req=""; break; } if (c == '\n') currentLineIsBlank = true; else if (c != '\r') currentLineIsBlank = false; } } delay(1); client.stop(); } time_current=millis(); // обновление метки времени encoder(); service_encoder(); } void readEncoder(uint8_t pin1, uint8_t pin2) // сервисная функция датчиков холла { uint8_t gray_code = digitalRead(pin1) | (digitalRead(pin2) << 1); if (gray_code != prev_state) { current_seq <<= 2; current_seq |= gray_code; prev_state = gray_code; } } void sendError () { llCount = 0; lrCount = 0; stage = 0; Serial.println("Error!"); } void nextStage () { llCount = 0; lrCount = 0; stage++; Serial.print("Next stage: "); Serial.println(stage); } void encoder() //функция логической части энкодера { if (stage == 0) { if (lrCount == 3 && llCount == 0) { nextStage(); } else if (llCount > 0) { sendError(); } } if (stage == 1) { if (lrCount == 0 && llCount == 2) { nextStage(); } else if (lrCount > 0) { sendError(); } } if (stage == 2) { if (lrCount == 1 && llCount == 0) { nextStage(); } else if (llCount > 0) { sendError(); } } if (stage == 3) { if (lrCount == 0 && llCount == 2) { nextStage(); } else if (lrCount > 0) { sendError(); } } if (stage == 4) { if (lrCount == 2 && llCount == 0) { nextStage(); } else if (llCount > 0) { sendError(); } } } void service_encoder() { readEncoder(ENC_PIN1, ENC_PIN2); switch (current_seq) { case FORWARD_SEQ: Serial.print(">> "); Serial.println(llCount++); current_seq = 0; break; case BACKWARD_SEQ: Serial.print("<< "); Serial.println(lrCount++); current_seq = 0; break; } //для обновления времени encPosition = myEnc.read(); if (encPosition != oldencPosition) { enc_time = time_current; oldencPosition = encPosition; } if (stage == 0 && (time_current - enc_time > 1300)) //сброс по времени при бездействии { enc_time = time_current; sendError(); } if (stage != 0 && stage != 5 && (time_current - enc_time > 30000)) // сброс через 30сек после начала прохождения комбинации при бездействии { enc_time = time_current; sendError(); } if (stage == 5 && (time_current - enc_time > 3000)) // сброс после прохождения комбинации { enc_time = time_current; sendError(); } } В чем может быть проблема?
Разобрался с проблемой. Оказалось энкодеру мешает цикл общения Ethernet Shield с сетью. Из-за этого появляется задержка и алгоритм нестабильно работает. На счет Serial - ошибка в коде - Serial.println(lrCount++) Люди добрые, помогите дописать чтения кода Грея с прерываниями, буду очень благодарен!