Created
March 23, 2012 08:50
-
-
Save arduinoboard/2168557 to your computer and use it in GitHub Desktop.
The file that is currently on an Arduino Uno with a serial number of 64932343738351217080
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
/* | |
Copyright (c) 2011 Guy Carpenter | |
*/ | |
#include <Arduino.h> | |
#include "Command.h" | |
#define CMDBUF_LEN 40 | |
void Command::skipWhitespace(char **line, int *len) | |
{ | |
while (*len > 0 && **line == ' ') { | |
(*len)--; | |
(*line)++; | |
} | |
} | |
boolean Command::parseCommand(char **line, int *len, char *cmd) | |
{ | |
boolean result = false; | |
skipWhitespace(line, len); | |
if (*len > 0) { | |
*cmd = **line; | |
(*len)--; | |
(*line)++; | |
result = true; | |
} | |
return result; | |
} | |
boolean Command::parseInteger(char **line, int *len, value_t *value) | |
{ | |
boolean result = false; | |
*value = 0; | |
while (*len>0 && **line>='0' && **line<='9') { | |
*value = *value * 10 + (**line - '0'); | |
(*len)--; | |
(*line)++; | |
result = true; | |
} | |
return result; | |
} | |
boolean Command::parseTuple(char **line, int *len, value_t *tuple) | |
{ | |
boolean result = false; | |
skipWhitespace(line, len); | |
for (int i=0; i<COMMAND_TUPLE_LEN; i++) { | |
if (parseInteger(line, len, tuple+i+1)) { | |
result = true; | |
tuple[0] = i+1; | |
if (*len>0 && **line == ',') { | |
// found comma, so more integers expected | |
(*len)--; | |
(*line)++; | |
result = false; // need another int to succeed | |
} | |
else { | |
break; | |
} | |
} | |
else { | |
break; | |
} | |
} | |
return result; | |
} | |
boolean Command::parseLine(char *line, int len) | |
{ | |
boolean result = false; | |
if (parseCommand(&line, &len, &command) && | |
parseTuple(&line, &len, address) && | |
parseTuple(&line, &len, value)) { | |
result = true; | |
} | |
else { | |
Serial.println("$Error Invalid command syntax"); | |
} | |
return result; | |
} | |
boolean Command::parseInput() | |
{ | |
boolean result = false; | |
static char line[CMDBUF_LEN]; // NOT zero terminated | |
static int len = 0; | |
if (Serial.available()) { | |
char c = Serial.read(); | |
if (c==10 || c==13) { | |
result = parseLine(line, len); | |
len = 0; | |
} | |
else if (len < CMDBUF_LEN) { | |
line[len++] = c; | |
} | |
return result; | |
} | |
} | |
void Command::dump() | |
{ | |
Serial.print(command); | |
Serial.print(" "); | |
for (int i=0;i<address[0];i++) { | |
if (i>0) Serial.print(","); | |
Serial.print(address[i+1]); | |
} | |
Serial.print(" "); | |
for (int i=0;i<value[0];i++) { | |
if (i>0) Serial.print(","); | |
Serial.print(value[i+1]); | |
} | |
Serial.println(); | |
} | |
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
#ifndef Command_h | |
#define Command_h | |
#include <Arduino.h> | |
#define COMMAND_TUPLE_LEN 3 | |
typedef unsigned int value_t; | |
class Command | |
{ | |
public: | |
char command; | |
value_t address[COMMAND_TUPLE_LEN+1]; | |
value_t value[COMMAND_TUPLE_LEN+1]; | |
private: | |
void skipWhitespace(char**, int*); | |
boolean parseCommand(char **line, int *len, char *cmd); | |
boolean parseInteger(char **line, int *len, value_t *value); | |
boolean parseTuple(char **line, int *len, value_t *tuple); | |
boolean parseLine(char *line, int len); | |
public: | |
boolean parseInput(); | |
void dump(); | |
}; | |
#endif |
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
#include <SwitecX25.h> | |
#include "Command.h" | |
#include "RotaryEncoder.h" | |
#include "IntRotaryEncoder.h" | |
#include "LED.h" | |
#include "Switch.h" | |
///////////////////////////////////// | |
// 0 RX | |
// 1 TX | |
// 2 INT | |
// 3 PWM INT | |
// 4 | |
// 5 PWM | |
// 6 PWM | |
// 7 | |
// | |
// 8 | |
// 9 PWM | |
// 10 PWM | |
// 11 PWM | |
// 12 | |
// 13 | |
///////////////////////////////////// | |
Command cmd; | |
// 6 steps per rotation, so 60 degrees per step of motor | |
// 180:1 gear ration | |
// 1/3 degree per step of needle | |
// 315 degrees full-scale-deflection of needle | |
// limit to 232 degrees sweep for square thermo dials | |
// at 3 steps per degree is 696 steps | |
#define MOTOR_STEPS (696) | |
SwitecX25 motors[] = { | |
SwitecX25(MOTOR_STEPS, 4,5,6,7), | |
SwitecX25(MOTOR_STEPS, 8,9,11,12) | |
}; | |
const unsigned int motorCount = sizeof(motors)/sizeof(*motors); | |
//RotaryEncoder encoder(2,3); | |
//IntRotaryEncoder encoder; | |
LED leds[] = {LED(3), LED(10)}; | |
const unsigned int ledCount = sizeof(leds)/sizeof(*leds); | |
Switch switch1(A1); | |
Switch switch2(A0); | |
boolean active = true; | |
void setup(void) { | |
Serial.begin(9600); | |
Serial.print(motorCount); | |
Serial.print(" motors. "); | |
Serial.println("Go!"); | |
// excercise the code to override the acceleration table. | |
static unsigned short accelTable[][2] = { | |
{ 20, 3000}, | |
{ 100, 1000}, | |
{ 300, 600} | |
}; | |
motors[1].accelTable = accelTable; | |
motors[1].maxVel = accelTable[3-1][0]; | |
leds[0].speed = 0; | |
leds[1].speed = 1; | |
} | |
void loop(void) { | |
/* | |
{ | |
static int n = 0; | |
int delta = encoder.read(); | |
if (delta!=0) { | |
n += delta; | |
Serial.print(delta); | |
Serial.print(" "); | |
Serial.println(n); | |
} | |
int pos = motors[1].targetStep + delta; | |
if (pos<0) pos=motors[1].steps-1; | |
if (pos>=motors[1].steps) pos=0; | |
motors[1].setPosition(pos); | |
} | |
*/ | |
// switch1 on turns on light | |
if (switch1.changed()) { | |
Serial.print("switch1 "); | |
Serial.println(switch1.set ? "on" : "off"); | |
for (int i=0;i<ledCount;i++) { | |
leds[i].set(switch1.set ? 100 : 0); | |
} | |
} | |
// switch2 on turns everything off | |
if (switch2.changed()) { | |
Serial.print("switch2 "); | |
Serial.println(switch2.set ? "on" : "off"); | |
active = !switch2.set; | |
motors[0].setPosition(0); | |
motors[1].setPosition(0); | |
} | |
motors[0].update(); | |
motors[1].update(); | |
leds[0].update(); | |
leds[1].update(); | |
if (cmd.parseInput()) { | |
//cmd.dump(); | |
if (cmd.address[1]<motorCount) { | |
SwitecX25 *motor = motors+cmd.address[1]; | |
switch (cmd.command) { | |
case 'z': | |
motor->zero(); | |
break; | |
case 's': | |
if (active) motor->setPosition(cmd.value[1]); | |
break; | |
case 'r': | |
// r <n> <steps> set motor range | |
motor->steps = cmd.value[1]; | |
break; | |
case 'l': | |
LED *led = leds + cmd.address[1]; | |
led->set(cmd.value[1]); | |
break; | |
} | |
} | |
} | |
} | |
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
#include <Arduino.h> | |
#include "IntRotaryEncoder.h" | |
// interrupt 0 services pin 3 | |
#define INT0 0 | |
#define PIN0 2 | |
// interrupt 1 services pin 4 | |
#define INT1 1 | |
#define PIN1 3 | |
volatile int _pos1 = 0; | |
volatile int _pos2 = 0; | |
volatile int _lastPosition = 0; | |
// use separate counts because we handle two interrupts here | |
// and it appears they can overlap. | |
static void intRotaryEncoderISR() | |
{ | |
static byte lastData = 0x3; | |
byte data = (PIND >> 2) & 0x3; // pin3 and pin2 data | |
byte trigger = (lastData ^ data); | |
lastData = data; | |
if (trigger == 0x1) { // pin0 changed | |
_pos1 += ((data & 1) ^ data>>1) ? 1 : -1; | |
} else if (trigger == 0x2) { // pin1 changed | |
_pos2 += ((data & 1) ^ data>>1) ? -1 : 1; | |
} | |
} | |
IntRotaryEncoder::IntRotaryEncoder() | |
{ | |
pinMode(PIN0, INPUT); | |
digitalWrite(PIN0, HIGH); // enable internal pull-up resistors to avoid floating inputs | |
pinMode(PIN1, INPUT); | |
digitalWrite(PIN1, HIGH); // enable internal pull-up resistors to avoid floating inputs | |
attachInterrupt(INT0, intRotaryEncoderISR, CHANGE); | |
attachInterrupt(INT1, intRotaryEncoderISR, CHANGE); | |
} | |
int IntRotaryEncoder::read() | |
{ | |
int position = _pos1 + _pos2; | |
int delta = position - _lastPosition; | |
_lastPosition = position; | |
return delta; | |
} | |
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
#ifndef _IntRotaryEncoder_h_ | |
#define _IntRotaryEncoder_h_ | |
// Since the standard arduino only has interrupts for pins 2 and 3 | |
// the rotary encoder MUST be attached to those two pins. | |
class IntRotaryEncoder | |
{ | |
public: | |
IntRotaryEncoder(); | |
int read(); // returns signed delta | |
}; | |
#endif |
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
#include <Arduino.h> | |
#include "LED.h" | |
LED::LED(unsigned char pin) | |
{ | |
this->pin = pin; | |
this->target = 0; | |
this->value = 0; | |
this->speed = 0; // instant | |
pinMode(pin, OUTPUT); | |
analogWrite(pin, 0); | |
} | |
void LED::set(unsigned char value) | |
{ | |
if (this->speed==0) { | |
this->value = this->target = value; | |
analogWrite(pin, this->value); | |
} else { | |
this->target = value; | |
} | |
} | |
void LED::update() | |
{ | |
if (this->value != this->target) { | |
if (this->value < this->target) { | |
unsigned char delta = this->target-this->value; | |
if (delta > this->speed) delta = this->speed; | |
this->value+=delta; | |
} else { | |
unsigned char delta = this->value-this->target; | |
if (delta > this->speed) delta = this->speed; | |
this->value-=delta; | |
} | |
Serial.println(this->value); | |
analogWrite(pin, this->value); | |
} | |
} |
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
#ifndef LED_h | |
#define LED_h | |
class LED | |
{ | |
public: | |
unsigned char pin; | |
unsigned char target; | |
unsigned char value; | |
unsigned char speed; | |
LED(unsigned char pin); | |
void set(unsigned char value); | |
void update(); | |
}; | |
#endif |
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
#include <Arduino.h> | |
#include "RotaryEncoder.h" | |
RotaryEncoder::RotaryEncoder(unsigned char pin1, unsigned char pin2) | |
{ | |
this->pin1 = pin1; | |
this->pin2 = pin2; | |
pinMode(pin1, INPUT); | |
digitalWrite(pin1, HIGH); // enable internal pull-up resistors to avoid floating inputs | |
pinMode(pin2, INPUT); | |
digitalWrite(pin2, HIGH); | |
} | |
int RotaryEncoder::read() | |
{ | |
int delta = 0; | |
static unsigned char lastData = 0; | |
unsigned char data = (PIND >> 2) & 0x3; | |
unsigned char change = data ^ lastData; | |
if (change & 0x1) { // pin0 changed | |
delta += ((data & 1) ^ data>>1) ? +1 : -1; | |
} else if (change & 0x2) { // pin1 changed | |
delta += ((data & 1) ^ data>>1) ? -1 : +1; | |
} | |
lastData = data; | |
return delta; | |
} |
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
#ifndef RotaryEncoder_h | |
#define RotaryEncoder_h | |
// Sequence moving forward: | |
// 1 1 << stable state | |
// | |
// 1 1 << moving forward | |
// 1 0 | |
// 0 0 | |
// 0 1 | |
// 1 1 | |
// | |
// 1 1 << moving backwards | |
// 0 1 | |
// 0 0 | |
// 1 0 | |
// 1 1 | |
// | |
// FWD: 3 1 0 2 3 | |
// was 0 now 1 : fwd | |
// was 1 now 3 : fwd | |
// was 2 now 0 : fwd | |
// was 3 now 2 : fwd | |
// | |
// REV: 3 2 0 1 3 | |
// was 0 now 2 : rev | |
// was 1 now 0 : rev | |
// was 2 now 3 : rev | |
// was 3 now 1 : rev | |
// | |
// | |
class RotaryEncoder | |
{ | |
public: | |
unsigned char pin1; | |
unsigned char pin2; | |
RotaryEncoder(unsigned char pin1, unsigned char pin2); | |
int read(); | |
}; | |
#endif |
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
#include <Arduino.h> | |
#include "Switch.h" | |
Switch::Switch(unsigned char pin) | |
{ | |
this->pin = pin; | |
this->set = false; | |
pinMode(pin, INPUT); // set pin to input | |
digitalWrite(pin, HIGH); // turn on pullup resistors | |
} | |
boolean Switch::isSet() | |
{ | |
return 0==digitalRead(this->pin); | |
} | |
// if changed returns true, check sw.set for new value | |
boolean Switch::changed() | |
{ | |
boolean wasSet = this->set; | |
this->set = this->isSet(); | |
return (this->set != wasSet); | |
} |
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
#ifndef Switch_h | |
#define Switch_h | |
class Switch | |
{ | |
public: | |
unsigned char pin; | |
boolean set; | |
Switch(unsigned char pin); | |
boolean isSet(); | |
boolean changed(); | |
}; | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment