/* created 2015 by Thomas Schuett, thomas at roboshock dot de This is a way to react on whole messages while ensuring, that the program will not temporarily hang due to throttling incoming data. Actually this approach may be oversized for the plain purpose of reducing the fan speed. */ int fanPin = 2; // if set LOW, the fan will blow boolean debug = true; // ring buffer for receive data to create a message queue system char inbuf[256]; int inbufLen = 256; int inbufNextReadPos = 0; int inbufNextWritePos = 0; // ================================================================================ void setup() { Serial.begin(9600); pinMode(fanPin, OUTPUT); digitalWrite(fanPin, HIGH); pinMode(fanPin, INPUT); } // ================================================================================ void loop() { exec_one_instruction(); } // returns, if there may be further commands to be executed now boolean exec_one_instruction() { if (! isMsgAvailable()) { return false; } while (is2MsgAvailable()) { // at least 2 msg in the queue if (debug) Serial.println("Skip one msg,"); client_consumeToLineEnd(); } char c = client_peek(); if (c == 'P') { // the command to spin down the fan for the next second client_read(); // consume this char int prozent = client_readInteger(); // consumes any preceding blanks first client_consumeToLineEnd(); if (debug) Serial.print("Got percent: "); if (debug) Serial.println(prozent, DEC); stopFan(prozent); } else { // ignore everything till next \n client_consumeToLineEnd(); } return true; } // creates a pulsed output with pulse length of 100 ms, for a total duration of 1.2 sec void stopFan(int proz) { if (proz == 0) return; for (int i=0; i < 12; i++) { // 1.2 sec total delay, because the PC may need more than 1.0 sec for next msg. pinMode(fanPin, OUTPUT); digitalWrite(fanPin, HIGH); delay(proz); pinMode(fanPin, INPUT); delay(100 - proz); } } // ========================================================== int client_readInteger() { client_consumeBlanks(); char intStr[10]; int pos = 0; intStr[pos] = 0; while (true) { char c = client_peek(); if ( c >= 0x30 && c <= 0x39) { intStr[pos] = c; intStr[pos+1] = 0; pos++; client_read(); // consume it if (pos >= 8) break; } else { break; } } return atoi(intStr); } void client_consumeBlanks() { while (true) { char c = client_peek(); if ( c == ' ') { client_read(); // consume it } else { break; } } } void client_consumeToLineEnd() { char c = client_read(); // ignore everything till next \n while (c != '\n') { c = client_read(); } } // ========================================================== // recall from above: //char inbuf[256]; //int inbufLen = 256; //int inbufNextReadPos = 0; //int inbufNextWritePos = 0; uint8_t localBuf[256]; void fillReadBuffer() { fillReadBuffer_serial(); } void fillReadBuffer_serial() { while (Serial.available() > 0) { byte c = Serial.read(); inbuf[inbufNextWritePos] = c; inbufNextWritePos++; if (inbufNextWritePos == inbufLen) inbufNextWritePos = 0; } } boolean isMsgAvailable() { fillReadBuffer(); int nextReadPos = inbufNextReadPos; while (nextReadPos != inbufNextWritePos) { if (inbuf[nextReadPos] == '\n') return true; nextReadPos++; if (nextReadPos == inbufLen) nextReadPos =0; } return false; } boolean is2MsgAvailable() { fillReadBuffer(); int nextReadPos = inbufNextReadPos; boolean found1 = false; while (nextReadPos != inbufNextWritePos) { if (inbuf[nextReadPos] == '\n') { if (found1) { return true; } else { found1 = true; } } nextReadPos++; if (nextReadPos == inbufLen) nextReadPos =0; } return false; } char client_read() { if (inbufNextReadPos == inbufNextWritePos) return '\n'; // quick n dirty // (should never happen, as it will only be called after a isMsgAvailable() returned true) char ret = inbuf[inbufNextReadPos]; inbufNextReadPos++; if (inbufNextReadPos == inbufLen) inbufNextReadPos = 0; return ret; } char client_peek() { if (inbufNextReadPos == inbufNextWritePos) return '\n'; // quick n dirty // (should never happen, as it will only be called after a isMsgAvailable() returned true) return inbuf[inbufNextReadPos]; } // ========================================================== void blink() { digitalWrite(13, HIGH); // set the LED on delay(200); // wait for a second digitalWrite(13, LOW); // set the LED off delay(500); // wait for a second } void blink2() { digitalWrite(13, HIGH); // set the LED on delay(100); // wait for a second digitalWrite(13, LOW); // set the LED off delay(100); // wait for a second }