Created
November 2, 2012 04:27
-
-
Save carlcrott/3998720 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
// OSH orbital shaker: www.black-glass.com | |
// TYVM Mayhew Labs: www.mayhewlabs.com/products/rotary-encoder-led-ring | |
// TYVM Mike McCauley: www.open.com.au/mikem/arduino/AccelStepper/ | |
#include <AccelStepper.h> | |
// ####### Encoder Variables ####### | |
//These are the pins that will talk to the shift register through SPI | |
#define SDI 11 //Data | |
#define CLK 12 //Clock | |
#define LE 13 //Latch | |
//These are the rotary encoder pins A, B, and switch | |
#define ENC_A 8 | |
#define ENC_B 9 | |
#define ENC_SW 10 | |
#define ENC_PORT PINB //The port that the rotary encoder is on (see http://www.arduino.cc/en/Reference/PortManipulation) | |
// Global variables | |
int scaledCounter = 0; //The LED output is based on a scaled veryson of the rotary encoder counter | |
int sequenceNumber = 0; //The output sequence for the LEDs | |
int incomingByte = 0; //Serial input to select LED output sequence | |
int switch_spool = 0; //Counts the loops where switch is in LOW state ... used to power off machine | |
int power_state = 1; // Stores current power state | |
// 16 LEDs on the ring.... each line has 16 bits with the 1 being on and 0 being off ... for that LED | |
unsigned int sequence[1][16] = {{ | |
0b1000000000000000, // This has a single LED turned on | |
0b1000000000000001, // This has the fist and last LEDs on and the rest off. | |
0b1000000000000011, | |
0b1000000000000111, | |
0b1000000000001111, | |
0b1000000000011111, | |
0b1000000000111111, | |
0b1000000001111111, | |
0b1000000011111111, | |
0b1000000111111111, | |
0b1000001111111111, | |
0b1000011111111111, | |
0b1000111111111111, | |
0b1001111111111111, | |
0b1011111111111111, | |
0b1111111111111111 // This is all LEDs turned on | |
}}; | |
// ####### Stepper Driver Variables ####### | |
AccelStepper myStepper( 1, 6, 7 ); // initialize AccelStepper in step/dir mode on pins 8 and 9 | |
const int RUN_PIN = 5; // On - Off switch | |
const int FREQ_PIN = 4; // High - Low frequency pin ( 2hz or 3hz ) | |
const int ON_PIN = 3; // On - Off switch | |
int targetFreq = 0; | |
int previousFreq = 0; | |
int buttonState = 0; // variable for storing the RUN_PIN status | |
// counts the number of cycles for reading inputs | |
// starts at 10000 so all inputs are read on first cycle | |
int run_cycle_count = 100000; | |
void setup() { | |
// ####### Encoder Setup ####### | |
//Set SPI pins to output | |
pinMode(SDI, OUTPUT); | |
pinMode(CLK, OUTPUT); | |
pinMode(LE, OUTPUT); | |
//Set encoder pins to input, turn internal pull-ups on | |
pinMode(ENC_A, INPUT); | |
digitalWrite(ENC_A, HIGH); | |
pinMode(ENC_B, INPUT); | |
digitalWrite(ENC_B, HIGH); | |
pinMode(ENC_SW, INPUT); | |
digitalWrite(ENC_SW, HIGH); | |
// ####### Stepper Driver Setup ####### | |
// initialize input pins | |
pinMode( RUN_PIN, INPUT ); | |
pinMode( FREQ_PIN, INPUT ); | |
pinMode( ON_PIN, OUTPUT ); | |
myStepper.setAcceleration( 200.0 ); | |
// ####### General Setup ####### | |
Serial.begin(115200); | |
} | |
void loop() | |
{ | |
//Local Variables | |
static uint8_t counter = 0; //this variable will be changed by encoder input | |
int8_t tmpdata; | |
if ( digitalRead( ENC_SW ) == LOW ){ | |
// spool 100 times to ensure we're not getting a false positive | |
if ( switch_spool >= 100 ){ | |
if ( power_state == 1 ){ | |
Serial.print(" POWERING OFF "); | |
// So tell the user to hold the button till they hear it spooling down | |
slow_to_zero(); | |
power_state = 0; | |
} | |
if ( power_state == 0 ){ | |
Serial.print(" POWERING UP "); | |
power_state = 1; | |
} | |
} | |
switch_spool++; | |
} else { | |
switch_spool = 0; | |
} | |
//Call read_encoder() function | |
tmpdata = read_encoder(); | |
//if the encoder has moved | |
if(tmpdata) { | |
// Set the new counter value of the encoder | |
// Scale by factor of 4 so that each physical encoder click... lights or extinguishes a LED | |
// Explanation: | |
// Each encoder-click changes the "counter" value by about 4 | |
// multiply that by 4 and you've got 16 | |
// 256 ( the total number of possible values from 0 - 255 ) | |
// 256 / 16 = 16 therefore each click is scaled to be exactly 1 LED | |
// And therefore each click accounts for 1/16th the total value of the int8_t of scaledCounter | |
counter += tmpdata * 4; | |
//Scale the counter value for referencing the LED sequence | |
//***NOTE: Change the map() function to suit the limits of your rotary encoder application. | |
// The first two numbers are the lower, upper limit of the rotary encoder, the | |
// second two numbers 0 and 15 are limits of LED sequence arrays. This is done | |
// so that the LEDs can use a different scaling than the encoder value. | |
scaledCounter = map(counter, 0, 255, 0, 16); | |
//scaledCounter = ( counter / 255) * 16; | |
//Print out the counter value | |
//Serial.print("scaled value: "); | |
//Serial.println(counter, DEC); | |
//Send the LED output to the shift register | |
digitalWrite(LE,LOW); | |
shiftOut(SDI,CLK,MSBFIRST,(sequence[sequenceNumber][scaledCounter] >> 8)); //High byte first | |
shiftOut(SDI,CLK,MSBFIRST,sequence[sequenceNumber][scaledCounter]); //Low byte second | |
digitalWrite(LE,HIGH); | |
} | |
} | |
// Returns change in encoder state (-1,0,1) | |
// www.circuitsathome.com/mcu/reading-rotary-encoder-on-arduino | |
int8_t read_encoder() { | |
int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0}; | |
static uint8_t old_AB = 0; | |
/**/ | |
old_AB <<= 2; //remember previous state | |
old_AB |= ( ENC_PORT & 0x03 ); //add current state | |
return ( enc_states[( old_AB & 0x0f )]); | |
} | |
void toggled() { | |
//toggle_switch = !toggle_switch; | |
//Serial.println( toggle_switch ); | |
} | |
void slow_to_zero() { | |
if ( myStepper.speed() > 0 ) | |
myStepper.moveTo( myStepper.currentPosition() + 1000 ); | |
// Blocks while it slows to zero | |
while ( myStepper.speed() > 0 ) | |
myStepper.run(); | |
Serial.println("stopped"); | |
digitalWrite( ON_PIN, LOW ); | |
delay( 1000 ); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment