//includes #include //constants //STP(serial to parallel), daisy-chained, shared clock, shared latch for output of the 8 7-segment displays const byte STP_Out_1_dataPin = 5; //75HC595_1 Pin14 const byte STP_Out_1_latchPin = 6; //75HC595_1 Pin12 const byte STP_Out_1_clockPin = 7; //75HC595_1 Pin11 //PTS(parallel to serial) for button input const byte PTS_In_1_latchPin = 11; //74HC165 Pin1 const byte PTS_In_1_clockPin = 13; //74HC165 Pin2 const byte PTS_In_1_dataPin = 12; //74HC165 Pin9 //CNY70-sensor (used as light-barrier for rolling-mechanism) const byte CNY70_In_Pin = 0; /*CNY seen from above, printed side showing to the right: pin1: connected to vcc aka blau aka 4 pin2: connected to gnd aka grau aka 3 pin3: connected to vcc aka grĂ¼n aka 2 pin4: connected to gnd (via pulldown) aka gelb aka 1 */ //L293B to turn the DC-motor clockwise/counter-clockwise const byte DCmotor_OutPin1 = 9; //L293B Pin2 const byte DCmotor_OutPin2 = 10; //L293B Pin7m //global variables int i=0; const unsigned long wheel_circumfence = 213; volatile unsigned long wheelturns_count_shortdist = 0; //for short distance display volatile unsigned long wheelturns_count_longdist = 0; //for high distance display unsigned long short_distance_val = 0; unsigned long long_distance_val = 0; const byte impulses_per_wheelturn = 6; //max is 255(!) volatile byte wheelturn_impulses_count = 0; //max is 255(!) byte CharArray[11]; //filled in setup() byte SevenSegArray[8]; //filled in setup() byte input_state_arr[8]; byte input_state_arr_prev[8]; long input_millis_arr[8]; long lastaction_arr[8]; byte sensor_disabled = 0; byte scroll_direction = 0; //0-not scrolling; 1 scrolling forward, 2 scroling reverse long scroll_start; long temp_timediff; void setup() { //output pinMode(STP_Out_1_dataPin, OUTPUT); pinMode(STP_Out_1_latchPin, OUTPUT); pinMode(STP_Out_1_clockPin, OUTPUT); pinMode(PTS_In_1_latchPin, OUTPUT); pinMode(PTS_In_1_clockPin, OUTPUT); //input pinMode(PTS_In_1_dataPin, INPUT); //interrupts attachInterrupt(0, wheelturn_interrupt, FALLING); attachInterrupt(1, poweroff_interrupt, FALLING); //local variables byte *ptr; //read saved values from EEPROM //read shortdist ptr = (byte*)&wheelturns_count_shortdist; for(i=0;i<4;i++) { *ptr = EEPROM.read(i); *ptr++; } //read longtdist ptr = (byte*)&wheelturns_count_longdist; for(i=4;i<8;i++) { *ptr = EEPROM.read(i); *ptr++; } //read impulses wheelturn_impulses_count = EEPROM.read(8); /* pinassignment 74HC595-->segment Q0 --> a (LSB) Q1 --> b Q2 --> c Q3 --> d Q4 --> e Q5 --> f Q6 --> g Q7 --> DP (MSB) */ CharArray[0] = 0xDD; //0 CharArray[1] = 0x05; //1 CharArray[2] = 0x9B; //2 CharArray[3] = 0x97; //3 CharArray[4] = 0x47; //4 CharArray[5] = 0xD6; //5 CharArray[6] = 0xDE; //6 CharArray[7] = 0x85; //7 CharArray[8] = 0xDF; //8 CharArray[9] = 0xD7; //9 CharArray[10] = 0x20; //. //to successively activate each of the eight 7seg displays SevenSegArray[0] = 0x01; SevenSegArray[1] = 0x02; SevenSegArray[2] = 0x04; SevenSegArray[3] = 0x08; SevenSegArray[4] = 0x10; SevenSegArray[5] = 0x20; SevenSegArray[6] = 0x40; SevenSegArray[7] = 0x80; } void loop() { //disable parallel read for 74HC165 to get the serial data digitalWrite(PTS_In_1_latchPin, HIGH); //get the serial data sshiftIn(); //re-enable parallel read for 74HC165 digitalWrite(PTS_In_1_latchPin, LOW); //to detect if button is held down for(i=0; i<8; i++) { if(input_state_arr[i] != input_state_arr_prev[i]) { input_millis_arr[i] = millis(); } input_state_arr_prev[i] = input_state_arr[i]; } //MAIN-LOGIC if(input_state_arr[0] && millis()-lastaction_arr[0]>300) { //scroll forward if((millis()-input_millis_arr[0])>2000) { //scroll forever sensor_disabled = 1; digitalWrite(DCmotor_OutPin1, HIGH); digitalWrite(DCmotor_OutPin2, LOW); lastaction_arr[0] = millis(); scroll_direction = 1; } else { if(scroll_direction == 2) { //stop motor digitalWrite(DCmotor_OutPin1, HIGH); digitalWrite(DCmotor_OutPin2, HIGH); lastaction_arr[0] = millis(); scroll_direction = 0; sensor_disabled = 0; } else { //scroll to next pos scroll_start = millis(); digitalWrite(DCmotor_OutPin1, HIGH); digitalWrite(DCmotor_OutPin2, LOW); lastaction_arr[0] = millis(); scroll_direction = 1; sensor_disabled = 0; } } } if(input_state_arr[1] && millis()-lastaction_arr[1]>300) { //roll down if((millis()-input_millis_arr[1])>2000) { //scroll forever sensor_disabled = 1; digitalWrite(DCmotor_OutPin1, LOW); digitalWrite(DCmotor_OutPin2, HIGH); lastaction_arr[1] = millis(); scroll_direction = 2; } else { if(scroll_direction == 1) { //stop motor digitalWrite(DCmotor_OutPin1, HIGH); digitalWrite(DCmotor_OutPin2, HIGH); lastaction_arr[1] = millis(); scroll_direction = 0; sensor_disabled = 0; } else { //scroll to next pos scroll_start = millis(); digitalWrite(DCmotor_OutPin1, LOW); digitalWrite(DCmotor_OutPin2, HIGH); lastaction_arr[1] = millis(); scroll_direction = 2; sensor_disabled = 0; } } } if(input_state_arr[2] && millis()-lastaction_arr[2]>300) { //manually increase distance wheelturns_count_shortdist += 5; wheelturns_count_longdist += 5; lastaction_arr[2] = millis(); } if(input_state_arr[3] && millis()-lastaction_arr[3]>300) { //manually decrease distance //make sure that value cannot become "smaller" than 0 if(wheelturns_count_shortdist >= 5) { wheelturns_count_shortdist -= 5; } else { wheelturns_count_shortdist = 0; } //make sure that value cannot become "smaller" than 0 if(wheelturns_count_longdist >= 5) { wheelturns_count_longdist -= 5; } else { wheelturns_count_longdist = 0; } lastaction_arr[3] = millis(); } if(input_state_arr[4]) { //reset displays //short-press: reset short-distance-display temp_timediff = millis() - input_millis_arr[4]; if(temp_timediff>2000 && temp_timediff<2500) { wheelturns_count_shortdist = 0; wheelturn_impulses_count = 0; //Serial.println("reset short"); lastaction_arr[4] = millis(); } //long-press: reset long-distance-display if(temp_timediff>5000) { wheelturns_count_longdist = 0; wheelturn_impulses_count = 0; //Serial.println("reset long"); lastaction_arr[4] = millis(); } } //ROADBOOK-SCROLLING if(!sensor_disabled) { if((millis()-scroll_start)>600) //ensure that sensor doesn't read same hole as started { if(analogRead(CNY70_In_Pin)<500) { //stop motor digitalWrite(DCmotor_OutPin1, HIGH); digitalWrite(DCmotor_OutPin2, HIGH); scroll_direction = 0; } } } //OUTPUT print_distances(); } void printout(byte displayVal2[4], byte displayVal1[4]) { byte temparray[8]; byte data; //merge the two arrays for(i=0; i<4; i++) { temparray[i] = displayVal1[i]; temparray[i+4] = displayVal2[i]; } for(i=0; i<=7; i++) { //load data to 75HC595s -> gets shifted through since they're daisy-chained shiftOut(STP_Out_1_dataPin, STP_Out_1_clockPin, MSBFIRST, SevenSegArray[i]); shiftOut(STP_Out_1_dataPin, STP_Out_1_clockPin, MSBFIRST, temparray[i]); //activate data output of the 75HC595s digitalWrite(STP_Out_1_latchPin, 1); delay(1); digitalWrite(STP_Out_1_latchPin, 0); } } void wheelturn_interrupt() { wheelturn_impulses_count++; if(wheelturn_impulses_count == impulses_per_wheelturn) { wheelturns_count_shortdist++; wheelturns_count_longdist++; wheelturn_impulses_count = 0; } } void poweroff_interrupt() { //in case of poweroff write the values of wheelturns (long & short) //and the current count of received impulses (partial turns) to EEPROM byte *ptr; //write shortdist ptr = (byte*)&wheelturns_count_shortdist; for(i=0; i<4; i++) { EEPROM.write(i, *ptr); *ptr++; } //write longdist ptr = (byte*)&wheelturns_count_longdist; for(i=4; i<8; i++) { EEPROM.write(i, *ptr); *ptr++; } //write impulses EEPROM.write(8, wheelturn_impulses_count); } void sshiftIn() { for(i=0; i<=7; i++) { digitalWrite(PTS_In_1_clockPin, LOW); delayMicroseconds(3); input_state_arr[7-i] = digitalRead(PTS_In_1_dataPin); //shift the next bit (rising edge triggered) digitalWrite(PTS_In_1_clockPin, HIGH); delayMicroseconds(3); } } void print_distances() { byte display1[4]; byte display2[4]; short_distance_val = wheelturns_count_shortdist * wheel_circumfence; short_distance_val /= 1000; for(i=3; i>=0; i--) { display1[i] = CharArray[short_distance_val % 10]; short_distance_val /= 10; } //adding decimal point display1[1] = display1[1] | CharArray[10]; long_distance_val = wheelturns_count_longdist * wheel_circumfence; long_distance_val /= 10000; for(i=3; i>=0; i--) { display2[i] = CharArray[long_distance_val % 10]; long_distance_val /= 10; } //adding decimal point display2[2] = display2[2] | CharArray[10]; printout(display2, display1); }