Quite some time has passed since I automated my manual filter wheel, so now I write the article. I built this one mainly for fun, I could afford the (overpriced) automated version.
The specifications behind the whole idea
- automate the manual filterwheel — without modifying the wheel itself, revert the changes should I get bored or if anything goes south
- make it fail gracefully: the DC motor can be driven by anything outputting around 5V, a manual H-bridge and a couple of AAA batteries for example. Experience: the first version with the encoder failed due to the intense sunlight — hence duct tape and a paper cover of the window were added. Failing gracefully meant disconnecting the logic and connecting the manual H-bridge. No observation wasted.
- make it compatible with my existing gear (the soapbox and the noszogtató)
Block diagrams
Photos
Desktop demo (English)
Field Demo, Observing Venus (Hungarian)
Source code
#define FILTERWHEEL_WELCOME_SCREEN_FIRST_LINE "FilterWheel v0.4" #define FILTERWHEEL_WELCOME_SCREEN_SECOND_LINE " csillagtura.ro " //#define FILTERWHEEL_PROJECT_DEBUG_MODE #include <AT24Cxx.h> #include <Wire.h> #include <LiquidCrystal_I2C.h> #define EEPROM_I2C_ADDRESS 0x50 AT24Cxx eep(EEPROM_I2C_ADDRESS, 32); LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display //=================== PINS ====================== #define PIN_MOTOR_RIGHT A0 #define PIN_MOTOR_LEFT A1 #define PIN_ROW_0 12 #define PIN_ROW_1 11 #define PIN_ROW_2 10 #define PIN_ROW_3 9 #define PIN_COL_0 8 #define PIN_COL_1 7 #define PIN_COL_2 6 #define PIN_COL_3 5 #define PIN_OPTO_ENABLE 4 #define PIN_OPTO_INPUT A2 #define PIN_MYSERIAL_TX 3 #define PIN_MYSERIAL_RX 2 //====================== KEYBOARD ========================== #define KEYBOARD_INPUT_LEN 10 char keyboardInput[KEYBOARD_INPUT_LEN]; int keyboardCursorRead = 0; int keyboardCursorWrite = 0; int keyboardCurrentColumn = 0; const char keyboardKeys[16] = {'1','2','3','A','4','5','6','B','7','8','9','C','*','0','#','D'}; char currentKey = 0; char keyboardCandidate = 0; char keyboardPreviousCandidate = 0; int keyboardCandidateObservedCount = 0; void keyboardInsert(char c){ int prev = keyboardCursorWrite - 1; if (prev == -1){ prev = KEYBOARD_INPUT_LEN - 1; } if (keyboardInput[prev] == c){ return ; } keyboardInput[keyboardCursorWrite] = c; keyboardCursorWrite++; if (keyboardCursorWrite >= KEYBOARD_INPUT_LEN ){ keyboardCursorWrite = 0; } } void keyboardInit(){ pinMode(PIN_ROW_0, INPUT_PULLUP); pinMode(PIN_ROW_1, INPUT_PULLUP); pinMode(PIN_ROW_2, INPUT_PULLUP); pinMode(PIN_ROW_3, INPUT_PULLUP); pinMode(PIN_COL_0, OUTPUT); pinMode(PIN_COL_1, OUTPUT); pinMode(PIN_COL_2, OUTPUT); pinMode(PIN_COL_3, OUTPUT); digitalWrite(PIN_COL_0, HIGH); digitalWrite(PIN_COL_1, HIGH); digitalWrite(PIN_COL_2, HIGH); digitalWrite(PIN_COL_3, HIGH); } void keyboardProcess(){ digitalWrite(PIN_COL_0, keyboardCurrentColumn == 0 ? LOW: HIGH); digitalWrite(PIN_COL_1, keyboardCurrentColumn == 1 ? LOW: HIGH); digitalWrite(PIN_COL_2, keyboardCurrentColumn == 2 ? LOW: HIGH); digitalWrite(PIN_COL_3, keyboardCurrentColumn == 3 ? LOW: HIGH); if (keyboardCurrentColumn == 0){ //full cycle, reset keyboardCandidate = 0; } if (digitalRead(PIN_ROW_0) == LOW){ keyboardCandidate = keyboardKeys[ 0*4 + keyboardCurrentColumn ]; } if (digitalRead(PIN_ROW_1) == LOW){ keyboardCandidate = keyboardKeys[ 1*4 + keyboardCurrentColumn ]; } if (digitalRead(PIN_ROW_2) == LOW){ keyboardCandidate = keyboardKeys[ 2*4 + keyboardCurrentColumn ]; } if (digitalRead(PIN_ROW_3) == LOW){ keyboardCandidate = keyboardKeys[ 3*4 + keyboardCurrentColumn ]; } keyboardCurrentColumn++; if (keyboardCurrentColumn > 3){ keyboardCurrentColumn = 0; } if (0 == keyboardCurrentColumn){ //a full cycle has been done if (keyboardCandidate == keyboardPreviousCandidate){ if (keyboardCandidateObservedCount > 100){ //we have a keypress keyboardInsert(keyboardCandidate); keyboardCandidateObservedCount = 0; }else{ keyboardCandidateObservedCount++; } }else{ keyboardCandidateObservedCount = 0; keyboardPreviousCandidate = keyboardCandidate; } } //Serial.print(candidate); } char keyboardGetCurrentKey(){ char r = 0; if (keyboardCursorRead != keyboardCursorWrite){ r = keyboardInput[keyboardCursorRead]; keyboardCursorRead = keyboardCursorWrite; }; return r; } #define OPTO_CHANGE_OBSERVED 1 #define OPTO_NO_CHANGE_OBSERVED 0 typedef struct OptoObserver { unsigned int changes; unsigned int observingSameStateCounter; byte observingState; byte observingPreviousState; byte currentState; byte optoIsObserving; } OptoObserver; OptoObserver optoObserver; void optoStart(){ digitalWrite(PIN_OPTO_ENABLE, HIGH); optoObserver.observingState = (digitalRead(PIN_OPTO_INPUT) == HIGH) ? 1 : 0; optoObserver.observingPreviousState = optoObserver.observingState; optoObserver.optoIsObserving = 1; } void optoStop(){ optoObserver.optoIsObserving = 0; digitalWrite(PIN_OPTO_ENABLE, LOW); } void optoInit(){ pinMode(PIN_OPTO_INPUT, INPUT_PULLUP); pinMode(PIN_OPTO_ENABLE, OUTPUT); digitalWrite(PIN_OPTO_ENABLE, LOW); optoObserver.optoIsObserving = 0; } byte optoObserverProcess(){ byte rez = OPTO_NO_CHANGE_OBSERVED; if (1 == optoObserver.optoIsObserving){ optoObserver.observingState = (digitalRead(PIN_OPTO_INPUT) == HIGH) ? 1 : 0; if (optoObserver.observingState == optoObserver.observingPreviousState){ optoObserver.observingSameStateCounter++; if (optoObserver.observingSameStateCounter > 200){ optoObserver.observingSameStateCounter = 200; } if (optoObserver.observingSameStateCounter > 100){ if (optoObserver.currentState != optoObserver.observingState){ optoObserver.currentState = optoObserver.observingState; //we have an event here optoObserver.changes++; rez = OPTO_CHANGE_OBSERVED; /* lcd.setCursor(0,1); char n[10]; itoa(changes, n, 10); lcd.print(n); lcd.print(" "); */ } } }else{ optoObserver.observingSameStateCounter = 0; } optoObserver.observingPreviousState = optoObserver.observingState; }else{ // the opto is turned off } return rez; } inline int chrToDir(char dir){ if (dir == 'L'){ return 1; }else{ return -1; }; } void(* resetFunc) (void) = 0; //declare reset function @ address 0 #define NUMBER_1_FILTER_INDEX_CHARACTER '\1' #define NUMBER_2_FILTER_INDEX_CHARACTER '\2' #define NUMBER_3_FILTER_INDEX_CHARACTER '\3' #define NUMBER_4_FILTER_INDEX_CHARACTER '\4' #define NUMBER_5_FILTER_INDEX_CHARACTER '\5' #define MOTOR_IS_STATIONARY_CHARACTER '\6' #define MOTOR_BACKSLASH_CHARACTER '\7' byte customBackslash[8] = { 0b00000, 0b10000, 0b01000, 0b00100, 0b00010, 0b00001, 0b00000, 0b00000 }; byte customDot[8] = { 0b00000, 0b00000, 0b00100, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000 }; /* byte customOneFilterIndex[8] = { 0b01000, 0b11000, 0b01001, 0b01000, 0b01001, 0b11100, 0b00000, 0b00000 }; byte customTwoFilterIndex[8] = { 0b01100, 0b10100, 0b00101, 0b01000, 0b10001, 0b11100, 0b00000, 0b00000 }; */ byte customOneFilterIndex[8] = { 0b01000, 0b11000, 0b01000, 0b01000, 0b11100, 0b00000, 0b00000, 0b00000 }; byte customTwoFilterIndex[8] = { 0b01000, 0b10100, 0b00100, 0b01000, 0b11100, 0b00000, 0b00000, 0b00000 }; byte customThreeFilterIndex[8] = { 0b11000, 0b00100, 0b01000, 0b00100, 0b11000, 0b00000, 0b00000, 0b00000 }; byte customFourFilterIndex[8] = { 0b00100, 0b01100, 0b10100, 0b11110, 0b00100, 0b00000, 0b00000, 0b00000 }; byte customFiveFilterIndex[8] = { 0b11100, 0b10000, 0b11100, 0b00100, 0b11000, 0b00000, 0b00000, 0b00000 }; inline void customCharsInit(){ lcd.createChar((byte) MOTOR_BACKSLASH_CHARACTER, customBackslash); lcd.createChar((byte) MOTOR_IS_STATIONARY_CHARACTER, customDot); lcd.createChar((byte) NUMBER_1_FILTER_INDEX_CHARACTER, customOneFilterIndex); lcd.createChar((byte) NUMBER_2_FILTER_INDEX_CHARACTER, customTwoFilterIndex); lcd.createChar((byte) NUMBER_3_FILTER_INDEX_CHARACTER, customThreeFilterIndex); lcd.createChar((byte) NUMBER_4_FILTER_INDEX_CHARACTER, customFourFilterIndex); lcd.createChar((byte) NUMBER_5_FILTER_INDEX_CHARACTER, customFiveFilterIndex); } //=================== MOTOR ===================== const char motorMovingCharacters[4] = { '/', '-', MOTOR_BACKSLASH_CHARACTER, '|' }; int motorMovingCharactersCursor = 0; int motorIsMoving = 0; unsigned long int motorOldMillis = 0; byte motorStoppedFlag = 0; void motorStop(byte updateScreen){ optoStop(); motorIsMoving = 0; motorSetDirectionPinsStateByDir(motorIsMoving); if (1 == updateScreen){ motorDrawMovementStatus(); } motorStoppedFlag = 1; } void motorInit(){ pinMode(PIN_MOTOR_LEFT, OUTPUT); pinMode(PIN_MOTOR_RIGHT, OUTPUT); motorStop(0); customCharsInit(); } #include <SoftwareSerial.h> SoftwareSerial mySerial(PIN_MYSERIAL_RX, PIN_MYSERIAL_TX); const int READ_BUFFER_LEN = 96; char filterWheelSerialReadBuffer[READ_BUFFER_LEN]; char mySerialReadBuffer[READ_BUFFER_LEN]; inline void mySerial_process(){ while (mySerial.available() > 0){ char c = mySerial.read(); if (c == '#'){ mySerialReadBuffer[0] = 0; }else{ if (c == '/'){ Serial.println("message from upstairs"); Serial.println(mySerialReadBuffer); command_process(mySerialReadBuffer, 1); }else{ //continue to concat int n = strlen(mySerialReadBuffer); if (n < READ_BUFFER_LEN - 2) { mySerialReadBuffer[n] = c; mySerialReadBuffer[n + 1] = 0; } } } } } inline void process_Serial(){ while (Serial.available() > 0) { char c = Serial.read(); if (c == '#') { filterWheelSerialReadBuffer[0] = 0; } else { if (c == '/') { command_process(filterWheelSerialReadBuffer, 0); //mySerial.write(filterWheelSerialReadBuffer); } else { //continue to concat int n = strlen(filterWheelSerialReadBuffer); if (n < READ_BUFFER_LEN - 2) { filterWheelSerialReadBuffer[n] = c; filterWheelSerialReadBuffer[n + 1] = 0; } } } }; } inline void serialInit(){ Serial.begin(9600); mySerial.begin(4800); } inline void serialProcess(){ process_Serial(); mySerial_process(); } void motorProcess(){ if (0 != motorIsMoving){ unsigned long int m = millis(); if (m > motorOldMillis+500){ motorOldMillis = m; motorMovingCharactersCursor++; if (motorMovingCharactersCursor >= 4){ motorMovingCharactersCursor = 0; } motorDrawMovementStatus(); } } if (1 == motorStoppedFlag){ motorStoppedFlag = 0; mySerial.println("#?fw:motstopd?/"); } } void motorStart(int dir){ if (dir == 0){ motorIsMoving = 0; }else{ optoStart(); if (dir > 0){ motorIsMoving = 1; }else{ motorIsMoving = -1; }; } motorDrawMovementStatus(); motorSetDirectionPinsStateByDir(motorIsMoving); if (dir == 0){ motorStop(1); } } inline void motorStartChrDir(char dir){ motorStart(chrToDir(dir)); } void motorSetDirectionPinsStateByDir(int dir){ digitalWrite(PIN_MOTOR_RIGHT, dir > 0 ? HIGH : LOW); digitalWrite(PIN_MOTOR_LEFT, dir < 0 ? HIGH : LOW); }; inline void motorPause(byte doPause){ motorSetDirectionPinsStateByDir((doPause == 0) ? motorIsMoving : 0); } void motorDrawMovementStatus(){ motorPause(1); lcd.setCursor(3,0); lcd.print( (0 != motorIsMoving ) ? motorMovingCharacters[motorMovingCharactersCursor] : MOTOR_IS_STATIONARY_CHARACTER ); motorPause(0); } // ================ WHEEL ==================== #define WHEEL_FILTERCOUNT 5 // N position: the number visible on the side, // F position: the filter actually loaded // F(N) = N % 5 + 1 #define COUNT_OF_CHANGES_BETWEEN_POSITIONS 123 #define WHEEL_FILTER_NAMES_ITEMSIZE 5 #define WHEEL_FILTER_NAMES_CHAR_ARRAY_SIZE ( WHEEL_FILTERCOUNT * WHEEL_FILTER_NAMES_ITEMSIZE ) #define WHEEL_FILTER_POSITION_ADDRESS 14 #define WHEEL_FILTER_NAMES_CHAR_ARRAY_ADDR (WHEEL_FILTER_POSITION_ADDRESS+2) char wheelFilterNamesCharArray[WHEEL_FILTER_NAMES_CHAR_ARRAY_SIZE]; byte wheelNamesReadFromEEPROM = 0; void wheelSaveNPosition(byte p){ eep.write(WHEEL_FILTER_POSITION_ADDRESS, p); }; byte wheelReadNPosition(){ signed char p = eep.read(WHEEL_FILTER_POSITION_ADDRESS); if (p < 1){ return 1; } if (p > WHEEL_FILTERCOUNT){ return 1; } return p; }; void wheelNamesToSerial(int destinationSerial){ #define FILTERNAMES_HEAD "?filtrNs=" #define FILTERNAMES_TAIL "?" if (0 == destinationSerial){ Serial.print('#'); Serial.print(FILTERNAMES_HEAD); for (uint16_t i=0; i<WHEEL_FILTER_NAMES_CHAR_ARRAY_SIZE; i++){ Serial.print(wheelFilterNamesCharArray[i]); } Serial.print(FILTERNAMES_TAIL); Serial.println('/'); } if (1 == destinationSerial){ //this guy may be slower, so just enqueue some Serial.println("destination is 1"); mySerial.print('#'); mySerial.print(FILTERNAMES_HEAD); for (uint16_t i=0; i<WHEEL_FILTER_NAMES_CHAR_ARRAY_SIZE; i++){ mySerial.print(wheelFilterNamesCharArray[i]); } mySerial.print(FILTERNAMES_TAIL); mySerial.println('/'); } } void wheelNamesWrite(){ Serial.println("writing to eeprom"); wheelNamesToSerial(0); for (uint16_t i=0; i<WHEEL_FILTER_NAMES_CHAR_ARRAY_SIZE; i++){ eep.write(WHEEL_FILTER_NAMES_CHAR_ARRAY_ADDR + i, wheelFilterNamesCharArray[i]); } wheelNamesReadFromEEPROM = 0; } void wheelNamesRead(int destinationSerial){ for (uint16_t i=0; i<WHEEL_FILTER_NAMES_CHAR_ARRAY_SIZE; i++){ wheelFilterNamesCharArray[i] = eep.read(WHEEL_FILTER_NAMES_CHAR_ARRAY_ADDR + i); } wheelNamesToSerial(destinationSerial); } void wheelNamesCachedRead(){ if (0 == wheelNamesReadFromEEPROM){ wheelNamesReadFromEEPROM = 1; wheelNamesRead(-1); } } byte wheelNamesToggleStatus = 1; void wheelNamesToggle(){ if (1 == wheelNamesToggleStatus){ wheelNamesToggleStatus = 0; wheelDisplayNPosition(0); lcd.setCursor(0,1); lcd.print("ABCD:move #d:set"); }else{ wheelNamesToggleStatus = 1; wheelDisplayNPosition(0); wheelNamesCachedRead(); lcd.setCursor(4,0); int i = 0; i+= 2; lcd.print(' '); lcd.print(' '); lcd.print(' '); lcd.print(NUMBER_1_FILTER_INDEX_CHARACTER); lcd.print(wheelFilterNamesCharArray[i++]); lcd.print(wheelFilterNamesCharArray[i++]); lcd.print(wheelFilterNamesCharArray[i++]); lcd.print(' '); i+= 2; lcd.print(NUMBER_2_FILTER_INDEX_CHARACTER); lcd.print(wheelFilterNamesCharArray[i++]); lcd.print(wheelFilterNamesCharArray[i++]); lcd.print(wheelFilterNamesCharArray[i++]); lcd.print(' '); lcd.setCursor(0,1); lcd.print(' '); lcd.print(' '); i += 2; lcd.print(NUMBER_3_FILTER_INDEX_CHARACTER); lcd.print(wheelFilterNamesCharArray[i++]); lcd.print(wheelFilterNamesCharArray[i++]); lcd.print(wheelFilterNamesCharArray[i++]); lcd.print(' '); i+= 2; lcd.print(NUMBER_4_FILTER_INDEX_CHARACTER); lcd.print(wheelFilterNamesCharArray[i++]); lcd.print(wheelFilterNamesCharArray[i++]); lcd.print(wheelFilterNamesCharArray[i++]); lcd.print(' '); i+= 2; lcd.print(NUMBER_5_FILTER_INDEX_CHARACTER); lcd.print(wheelFilterNamesCharArray[i++]); lcd.print(wheelFilterNamesCharArray[i++]); lcd.print(wheelFilterNamesCharArray[i++]); lcd.print(' '); } }; int wheelPosition = 1; int wheelStopAfter = 0; void wheelReportNPositionToSerialPorts(int isSetting){ Serial.print("#?wheel"); if (1 == isSetting){ Serial.print("Set"); }; Serial.print("Position="); Serial.print(wheelPosition); Serial.print("?/"); mySerial.print("#?wheelPosition="); mySerial.print(wheelPosition); mySerial.print("?/"); }; void wheelDisplayNPosition(int isSetting){ lcd.setCursor(0,0); lcd.print("N="); lcd.print(wheelPosition); lcd.print(" d:goto"); motorDrawMovementStatus(); wheelReportNPositionToSerialPorts(isSetting); } void wheelConsiderWeAreAtNPosition(int n){ wheelPosition = n; wheelSaveNPosition(n); wheelDisplayNPosition(1); }; void wheelMove(int dir, int count){ optoObserver.changes = 0; wheelStopAfter = abs(count) * COUNT_OF_CHANGES_BETWEEN_POSITIONS - 1; if (wheelStopAfter < 0){ wheelStopAfter = 0; } motorStart(dir); wheelPosition = wheelPosition + count*dir; while (wheelPosition > WHEEL_FILTERCOUNT){ wheelPosition -= WHEEL_FILTERCOUNT; } while (wheelPosition < 1){ wheelPosition += WHEEL_FILTERCOUNT; } wheelDisplayNPosition(0); } void wheelMoveFullCircleChrDir(char dir){ wheelMove(chrToDir(dir), WHEEL_FILTERCOUNT); }; inline void wheelMoveChrDir(char dir, int count){ wheelMove(chrToDir(dir), count); }; void wheelMarkInputStateChange(){ if (wheelStopAfter > 0){ wheelStopAfter--; if (wheelStopAfter == 0){ motorStop(1); } } } void wheelGotoNPosition(int n){ int zeroBasedCurrentPosition = wheelPosition - 1; int zeroBasedDestination = n - 1; int delta = zeroBasedDestination - zeroBasedCurrentPosition; if (abs(delta) > WHEEL_FILTERCOUNT / 2){ int s = delta < 0 ? -1 : 1; delta = (WHEEL_FILTERCOUNT - abs(delta))*(s*-1); } /* lcd.setCursor(0,1); lcd.print("delta="); lcd.print(delta); lcd.print(" "); */ wheelSaveNPosition(zeroBasedDestination + 1); wheelMove(-delta, -delta); wheelPosition = zeroBasedDestination + 1; wheelDisplayNPosition(1); } int wheelNextKeyIsNSetter = 0; void wheelMoveALittle(char dir, int steps){ wheelStopAfter = steps; motorStartChrDir(dir); } void wheelNamesSetIndexZ(int zi, char * subname, int doWrite){ if (zi < 0){ return ;//invalid index } if (zi >= WHEEL_FILTERCOUNT){ return ; // invalid index } #ifdef FILTERWHEEL_PROJECT_DEBUG_MODE Serial.print("Setting name "); Serial.print(zi); Serial.print(" to "); Serial.println(subname); #endif int i = zi*WHEEL_FILTER_NAMES_ITEMSIZE; wheelFilterNamesCharArray[i++] = zi+48+1; wheelFilterNamesCharArray[i++] = '='; byte j=0; for (byte k=0; k<WHEEL_FILTER_NAMES_ITEMSIZE-2;k++){ wheelFilterNamesCharArray[i+k] = (j<strlen(subname)) ? subname[j++] : ' '; } if (1 == doWrite){ wheelNamesWrite(); }; } int command_process(const char * filterWheelSerialReadBuffer, int destinationSerial){ if (strncmp(filterWheelSerialReadBuffer, "filter", 6) == 0){ wheelMoveChrDir(filterWheelSerialReadBuffer[6], 1); return 1; } if (strncmp(filterWheelSerialReadBuffer, "jump", 4) == 0){ wheelMoveALittle(filterWheelSerialReadBuffer[4], 10); return 1; } if (strncmp(filterWheelSerialReadBuffer, "move", 4) == 0){ wheelMoveALittle(filterWheelSerialReadBuffer[4], 4); return 1; } if (strncmp(filterWheelSerialReadBuffer, "step", 4) == 0){ wheelMoveALittle(filterWheelSerialReadBuffer[4], 1); return 1; } if (strncmp(filterWheelSerialReadBuffer, "atn,", 4) == 0){ wheelConsiderWeAreAtNPosition(filterWheelSerialReadBuffer[4] - 48); wheelStopAfter = 0; motorStop(1); return 1; } if (strncmp(filterWheelSerialReadBuffer, "goton,", 6) == 0){ wheelGotoNPosition(filterWheelSerialReadBuffer[6] - 48); return 1; } if (strncmp(filterWheelSerialReadBuffer, "goton=", 6) == 0){ wheelGotoNPosition(filterWheelSerialReadBuffer[6] - 48); return 1; } if (strncmp(filterWheelSerialReadBuffer, "wheren", 6) == 0){ wheelReportNPositionToSerialPorts(0); return 1; } if (strncmp(filterWheelSerialReadBuffer, "eepnames?", 9) == 0){ wheelNamesRead(destinationSerial); return 1; } if (strncmp(filterWheelSerialReadBuffer, "name",4)==0){ #ifdef DEBUG_MODE Serial.println(filterWheelSerialReadBuffer); #endif if (filterWheelSerialReadBuffer[4] == 's'){ // names=a,b,c,d,e,f,g,h char subname[16]; subname[0] = 0; int subnameIndex = 0; for (int i=6; i<64; i++){ if ((filterWheelSerialReadBuffer[i] == ',') || (filterWheelSerialReadBuffer[i] == 0)){ wheelNamesSetIndexZ(subnameIndex, subname, 0); if (filterWheelSerialReadBuffer[i] == 0){ wheelNamesWrite(); return ; } subname[0] = 0; subnameIndex++; }else{ int l = strlen(subname); if (l >= WHEEL_FILTER_NAMES_ITEMSIZE-1){ l = WHEEL_FILTER_NAMES_ITEMSIZE-2; } subname[l] = filterWheelSerialReadBuffer[i]; subname[l+1] = 0; } } //wheelNamesWrite(); }else{ // nameN=xyzqw strcat(filterWheelSerialReadBuffer, " "); int n = filterWheelSerialReadBuffer[4] - 48; wheelNamesSetIndexZ(n-1, filterWheelSerialReadBuffer+6, 1); } return 1; } return 0; } void setup(){ lcd.init(); lcd.backlight(); lcd.setCursor(0,0); lcd.print(FILTERWHEEL_WELCOME_SCREEN_FIRST_LINE); lcd.setCursor(0,1); lcd.print(FILTERWHEEL_WELCOME_SCREEN_SECOND_LINE); optoInit(); motorInit(); serialInit(); #ifndef FILTERWHEEL_PROJECT_DEBUG_MODE wheelNamesCachedRead(); wheelPosition = wheelReadNPosition(); delay(1000); #endif keyboardInit(); lcd.setCursor(0,0); lcd.print("Set the cur. N "); wheelNamesToggle(); #ifdef FILTERWHEEL_PROJECT_DEBUG_MODE Serial.println("debug mode"); wheelNamesRead(0); #endif } void loop() { if (OPTO_CHANGE_OBSERVED == optoObserverProcess()){ wheelMarkInputStateChange(); } serialProcess(); keyboardProcess(); motorProcess(); currentKey = keyboardGetCurrentKey(); if (currentKey != 0){ if (currentKey == '*'){ wheelNamesToggle(); } if (currentKey == '0'){ resetFunc(); } if (0 != motorIsMoving){ // do not execute keyboard commands }else{ if ((currentKey >= 49) && (currentKey <= 57)){ //if (currentKey == '8'){ wheelMoveFullCircleChrDir('R'); } if ((currentKey - 48) > WHEEL_FILTERCOUNT){ //invalid filter N position, zero already handled return ; } if (1 == wheelNamesToggleStatus){ wheelNamesToggle(); } if (1 == wheelNextKeyIsNSetter){ wheelConsiderWeAreAtNPosition(currentKey - 48); wheelStopAfter = 0; motorStop(1); }else{ wheelGotoNPosition(currentKey - 48); } } if (currentKey == '#'){ if (1 == wheelNextKeyIsNSetter){ wheelNextKeyIsNSetter = 0; wheelDisplayNPosition(0); }else{ wheelNextKeyIsNSetter = 1; lcd.setCursor(2,0); lcd.print('?'); } }else{ wheelNextKeyIsNSetter = 0; } if (currentKey == 'A'){ wheelMoveALittle('L', 4); } if (currentKey == 'D'){ wheelMoveALittle('R', 4); } if (currentKey == 'B'){ wheelMoveALittle('L', 2); } if (currentKey == 'C'){ wheelMoveALittle('R', 2); } } } }






