-
-
Save happyBanshee/daba08d9422b24a1764e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <SPI.h> | |
#include <LiquidCrystal.h> | |
#include <avr/io.h> | |
#include <avr/interrupt.h> | |
#include <ctype.h> | |
#include <math.h> | |
#include <avr/io.h> | |
#define HW_4017_RESET_PIN 47 | |
#define HW_4017_CLOCK_PIN 13 | |
#define _4017_RESET_PORT PORTB | |
#define _4017_CLOCK_PORT PORTB | |
#define _4017_RESET_DDR DDRB | |
#define _4017_CLOCK_DDR DDRB | |
#define _4017_RESET_PIN PINB0 | |
#define _4017_CLOCK_PIN PINB1 | |
#define SERVO_OCR OCR1A | |
#define SERVO_ENABLE OCIE1A | |
#define SERVO_FLAG OCF1A | |
#define SERVO_FORCE FOC1A | |
#define SERVO_COM0 COM1A0 | |
#define SERVO_COM1 COM1A1 | |
#if defined (__AVR_ATmega8__) | |
#define TIMER_SK TIMSK | |
#define TIMER_IFR TIFR | |
#define FORCE_REG TCCR1A | |
#else | |
#define TIMER_SK TIMSK1 | |
#define TIMER_IFR TIFR1 | |
#define FORCE_REG TCCR1C | |
#endif | |
#ifndef _BV | |
#define _BV(bit) (1 << (bit)) | |
#endif | |
#ifndef cbi | |
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) | |
#endif | |
#ifndef sbi | |
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) | |
#endif | |
#define CLOCK 16 | |
#define SYS_TICS_OF_USEC(us) (uint16_t)((us)*CLOCK) | |
#define Chop(_x, _min, _max) ( (_x) < (_min) ? (_min) : (_x) > (_max) ? (_max) : (_x) ) | |
#define SetServo(x, v) servo_widths[x] = SYS_TICS_OF_USEC(Chop(v,700,2400)); | |
#define _4017_NB_CHANNELS 10 | |
#define ON 1 | |
#define OFF 0 | |
#define OneSecond 1000 | |
#define ledPin 13 | |
unsigned int servo_widths[_4017_NB_CHANNELS]; | |
void Servo_4017_Set_Pulse_Width( int ServoNum, int pulseWidth ) | |
{ | |
servo_widths[ServoNum] = SYS_TICS_OF_USEC(pulseWidth); | |
} | |
void Servo_4017_init( void ) { | |
uint8_t i; | |
/* Configure 2 Arduino pins as outputs for controlling the 4017 reset and clock lines */ | |
digitalWrite(HW_4017_RESET_PIN, 0); | |
digitalWrite(HW_4017_CLOCK_PIN, 0); | |
pinMode(HW_4017_RESET_PIN, OUTPUT); | |
pinMode(HW_4017_CLOCK_PIN, OUTPUT); | |
digitalWrite(HW_4017_RESET_PIN, 1); // Reset the decade counter | |
digitalWrite(HW_4017_CLOCK_PIN, 0); // Lower the clock line | |
/* Set all servos at their midpoints */ | |
for( i=0 ; i < _4017_NB_CHANNELS ; i++ ) | |
servo_widths[i] = SYS_TICS_OF_USEC(1500); // SetServo(i,1500); | |
// ----------------------------------------------------------------------------------------- | |
// Configure Timer 1 and setup the Output Compare registers... | |
/* Timer1 @ Clk/1: System clock */ | |
TCCR1A = 0x00; | |
TCCR1B = _BV(CS10); | |
SERVO_OCR = 0x7FFF; /* Set servos to go off some long time from now */ | |
TCCR1A |= _BV(SERVO_COM0 ); /* Set output compare to toggle the output bits */ | |
#ifdef SERVOS_FALLING_EDGE | |
/* Starts CLOCK high for the falling edge case */ | |
FORCE_REG |= _BV(SERVO_FORCE); | |
// Serial.println("Falling Edge Active!"); | |
#endif | |
/* Clear the interrupt flags in case they are set */ | |
TIMER_IFR = _BV(SERVO_FLAG); | |
digitalWrite(HW_4017_RESET_PIN, 0); // Lower the decade counter reset line to start it running | |
/* Enable our output compare interrupts */ | |
TIMER_SK |= _BV(SERVO_ENABLE); | |
Serial.println("finish1"); | |
} | |
ISR( TIMER1_COMPA_vect ) | |
{ | |
static uint8_t servo = 0; | |
uint16_t width; | |
#ifdef SERVOS_FALLING_EDGE | |
#define RESET_WIDTH SYS_TICS_OF_USEC(1000) | |
#define FIRST_PULSE_WIDTH SYS_TICS_OF_USEC(100) | |
if (servo == _4017_NB_CHANNELS) { | |
sbi( _4017_RESET_PORT, _4017_RESET_PIN ); // set Reset pin high | |
/** Start a long 1ms reset, keep clock low */ | |
SERVO_OCR += RESET_WIDTH; | |
servo++; | |
return; | |
} | |
if (servo > _4017_NB_CHANNELS) { | |
/** Clear the reset, the clock has been toggled high */ | |
cbi( _4017_RESET_PORT, _4017_RESET_PIN ); // clear reset pin | |
/** Start a short pulse-like period */ | |
SERVO_OCR += FIRST_PULSE_WIDTH; | |
servo = 0; /* Starts a new sequence of pulses next time */ | |
return; | |
} | |
#else | |
if (servo >= _4017_NB_CHANNELS) { | |
sbi( _4017_RESET_PORT, _4017_RESET_PIN ); // set reset pin High | |
servo = 0; | |
// FIXME: 500 ns required by 4017 reset ???? why does it work without! | |
//asm( "nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;" ); | |
cbi( _4017_RESET_PORT, _4017_RESET_PIN ); // clear reset pin | |
} | |
#endif | |
width = servo_widths[servo]; | |
SERVO_OCR += width; | |
FORCE_REG |= _BV(SERVO_FORCE); | |
servo++; | |
} | |
void Servo_4017_init( void ); | |
void Servo_4017_Set_Pulse_Width( int ServoNum, int pulseWidth ); | |
// -------------------------------------------------------------------------------------------------------------------------------------------- | |
/* Global Variable definitions */ | |
uint16_t sWidth[8], sInc[8]; | |
unsigned long myTimer = 0; // general purpose timer | |
unsigned long OneSecTimer = 0; | |
int LED_On = 0; | |
LiquidCrystal lcd(12); | |
char keypressed = 0; | |
int keyboardPin = 0; // Analog input pin that the keypad is attached to | |
int keyboardValue = 0; // value read from the keyboard | |
int numCount = 0; | |
char pincode[4]; | |
int state; | |
void setup(){ | |
Serial.begin(9600); //hardware serial to PC | |
// setup LCD number of columns ans rows | |
lcd.begin(16, 2); | |
// print message on LCd | |
lcd.print("Enter the pin:"); | |
lcd.setCursor(0,1); | |
// servos | |
int n; | |
Serial.begin(9600); // debug output over serial line | |
pinMode(ledPin, OUTPUT); | |
digitalWrite(ledPin, ON); | |
LED_On = 1; | |
delay(OneSecond); | |
Serial.println("---"); | |
Serial.println("Arduino 4017 Servo Driver v1.0"); | |
delay(OneSecond); | |
digitalWrite(ledPin, OFF); | |
for (n=0; n<8; n++) // Set all servos to their center positions. | |
{ | |
sWidth[n] = 1500; | |
sInc[n] = 3; // setup each servo to move at a different speed | |
} | |
sInc[0] = 2; | |
Servo_4017_init(); /* Init Timer1 and setup Output Compare interrupt */ | |
digitalWrite(ledPin, ON); | |
OneSecTimer = millis(); | |
myTimer = millis(); | |
} | |
void precision_loop () | |
{ | |
int n; | |
if ((millis() - myTimer) >= 20) // 100ms is arbitrary interval for demo | |
{ | |
myTimer = millis(); | |
for (n=0; n<8; n++) // Keep servo 0 at center position - move all the rest. Demos NO jitter on Servo 0. | |
{ | |
sWidth[n] += sInc[n]; | |
Servo_4017_Set_Pulse_Width(n, sWidth[n]); | |
if ((sWidth[n] > 2100) || (sWidth[n] < 900)) // reverse direction at end of travel | |
sInc[n] = -sInc[n]; | |
} | |
} | |
if ((millis() - OneSecTimer) >= OneSecond) // this goes off once per second | |
{ | |
OneSecTimer = millis(); | |
LED_On = !LED_On; | |
digitalWrite(ledPin, LED_On); | |
} | |
} | |
void loop(){ | |
// keypad start | |
keyboardValue = analogRead(keyboardPin); | |
while (keyboardValue < 25){ | |
keyboardValue = analogRead(keyboardPin); | |
} | |
readkeyboard(); | |
// keypad end | |
precision_loop(); | |
} | |
void LcdClearLine(int r) | |
{ | |
lcd.setCursor(0, r); | |
for (int ii = 0; ii < 16; ii = ii + 1) { | |
lcd.print(" "); | |
} | |
} | |
//read the keyboard routine | |
void readkeyboard(){ | |
keyboardValue = analogRead(keyboardPin); // read the value (0-1023) | |
if (keyboardValue <25){keypressed = 0;} | |
if ((keyboardValue >25) && (keyboardValue < 67)){keypressed = '1';} | |
if ((keyboardValue >67) && (keyboardValue < 108)){keypressed = '2';} | |
if ((keyboardValue >108) && (keyboardValue < 162)){keypressed = '3';} | |
if ((keyboardValue >162) && (keyboardValue < 253)){keypressed = '4';} | |
if ((keyboardValue >253) && (keyboardValue < 361)){keypressed = '5';} | |
if ((keyboardValue >361) && (keyboardValue < 479)){keypressed = '6';} | |
if ((keyboardValue >479) && (keyboardValue < 619)){keypressed = '7';} | |
if ((keyboardValue >619) && (keyboardValue < 765)){keypressed = '8';} | |
if ((keyboardValue >765) && (keyboardValue < 819)){keypressed = '9';} | |
if ((keyboardValue >819) && (keyboardValue < 889)){keypressed = '*';} | |
if ((keyboardValue >889) && (keyboardValue < 938)){keypressed = '0';} | |
if (keyboardValue >938){keypressed = '#';} | |
//NOTE: the values used above are all halfway between the value obtained with each keypress in previous test sketch | |
while (keyboardValue > 25) { | |
//delay (100); | |
keyboardValue = analogRead(keyboardPin); // read the value (0-1023) | |
}//wait until key no longer being pressed before continuing | |
switch (keypressed) { | |
case '#': | |
Serial.println("ENTER"); | |
LcdClearLine(0); | |
lcd.setCursor(0, 0); | |
lcd.print("Welcome"); | |
lcd.setCursor(0, 1); | |
LcdClearLine(1); | |
// send pin to server to validate | |
break; | |
case '*': | |
Serial.println("RESET"); | |
// clean entered pincode | |
numCount = 0; | |
//pincode = char[4]; | |
LcdClearLine(0); | |
lcd.setCursor(0, 0); | |
lcd.print("Enter the pin:"); | |
LcdClearLine(1); | |
lcd.setCursor(0, 1); | |
break; | |
default: | |
//if(numCount != 4){ | |
pincode[numCount] = (char) keypressed; | |
Serial.println("NUM"); | |
lcd.write(keypressed); | |
//OpenServo(keypressed- '0'); | |
numCount++; | |
//} | |
} | |
Serial.println(keypressed); // print the value back to the Serial view window on your PC | |
// delay(1000); // wait 1000 milliseconds before the next loop | |
} | |
//end of read the keyboard routine |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment