Last active
August 29, 2015 14:16
-
-
Save Luit/bb867481931139fc9c5e 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
// kinda smart ergonomic Desk, or kseD for short, is a project to make my | |
// no-frills ergonomic desk a bit more special. | |
/* | |
Serial commands: | |
E <upper> <lower> | |
Read value from EEPROM (might disappear once testing is done) | |
G <upper> <lower> | |
Move to position (upper << 8 | lower) | |
I | |
Identify (triggers `kseD` update) | |
M <pos> | |
Move to stored position <pos> | |
P | |
Get position update | |
S <pos> <upper> <lower> | |
Store position (upper << 8 | lower) to <pos> | |
T | |
Show current target | |
X <user> | |
Switch user to <user>. User 0xFF means switching to normal mode. | |
Z | |
Zero the kseD (should be issued with desk in lowest position) | |
Serial updates: | |
C <size> <uid0> <uid1> ... <uid{size-1}> | |
New card detected | |
E <data> | |
Data from EEPROM (response to E command) | |
k 's' 'e' 'D' <version> | |
Response to I command | |
P <upper> <lower> | |
Position (upper << 8 | lower) reached (unsollicited means stored in EEPROM) | |
T <upper> <lower> | |
Current target is (upper << 8 | lower) | |
*/ | |
#include <SPI.h> | |
#include <EEPROM.h> | |
#include <MFRC522.h> | |
#define KSED_VERSION 0x02 | |
#define EEPROM_POSITION 0x000 // 2 bytes | |
#define EEPROM_CURRENT_USER 0x002 // 1 byte | |
#define EEPROM_CURRENT_POS 0x003 // 1 byte | |
#define EEPROM_USERS_OFFSET 0x100 // 768 bytes in 0x100 - 0x3FF (1K EEPROM) | |
#define EEPROM_MAX_USERS 192 // 768 bytes at 4 bytes per user | |
#define EEPROM_USER_LENGTH 4 // 2 bytes per position, 2 positions | |
#define ENCODER_PIN1 2 // Needs interrupt | |
#define ENCODER_PIN2 3 // Needs interrupt | |
#define RFID_RST_PIN 9 | |
#define RFID_SS_PIN 10 | |
#define UP_PIN 6 | |
#define DOWN_PIN 5 | |
volatile bool nfc = false; | |
volatile uint8_t lastEncoded = 0; | |
volatile uint16_t position; | |
volatile uint16_t sentPosition; | |
volatile uint32_t sentMs = 0; | |
volatile uint16_t target = 0; // 0 = no movement | |
volatile bool targetUp = false; // Direction of target at time of set | |
volatile uint8_t uidByte[10]; | |
volatile uint8_t uidSize = 0; | |
MFRC522 mfrc522(RFID_SS_PIN, RFID_RST_PIN); | |
void setup() { | |
position = EEPROM.read(EEPROM_POSITION); | |
if (position == 255<<8) { | |
position = 0x10; | |
// First time run, probably. | |
EEPROM.write(EEPROM_POSITION, 0x10); | |
EEPROM.write(EEPROM_POSITION+1, 0x00); | |
EEPROM.write(EEPROM_CURRENT_USER, 0xFF); | |
EEPROM.write(EEPROM_CURRENT_POS, 0x00); | |
} | |
position <<= 8; | |
position |= EEPROM.read(EEPROM_POSITION+1); | |
sentPosition = position; | |
pinMode(UP_PIN, OUTPUT); | |
pinMode(DOWN_PIN, OUTPUT); | |
digitalWrite(UP_PIN, LOW); | |
digitalWrite(DOWN_PIN, LOW); | |
// Initialize rotary encoder | |
pinMode(ENCODER_PIN1, INPUT); | |
pinMode(ENCODER_PIN2, INPUT); | |
digitalWrite(ENCODER_PIN1, HIGH); //turn pullup resistor on | |
digitalWrite(ENCODER_PIN2, HIGH); //turn pullup resistor on | |
//call updateEncoder() when any high/low changed seen | |
//on interrupt 0 (pin 2), or interrupt 1 (pin 3) | |
attachInterrupt(0, updateEncoder, CHANGE); | |
attachInterrupt(1, updateEncoder, CHANGE); | |
Serial1.begin (9600, SERIAL_8N1); | |
while (!Serial1); | |
// Enable SPI and activate RFID reader | |
SPI.begin(); // Init SPI bus | |
mfrc522.PCD_Init(); // Init MFRC522 | |
byte v = mfrc522.PCD_ReadRegister(mfrc522.VersionReg); | |
if (v == 0x91 || v == 0x92) { | |
nfc = true; // RFID chip found | |
// Enhance range of RFID reader | |
mfrc522.PCD_AntennaOff(); | |
mfrc522.PCD_SetAntennaGain(0xff); | |
mfrc522.PCD_AntennaOn(); | |
} | |
} | |
void serialWrite(byte b) { | |
Serial1.write(b); | |
} | |
void serialFlush() { | |
Serial1.flush(); | |
} | |
byte serialRead() { | |
while (Serial1.available() < 1); | |
return Serial1.read(); | |
} | |
void storePosition(bool now) { | |
if (sentPosition == position) { | |
sentMs = 0; | |
return; | |
} | |
if (!now && sentMs == 0) { | |
sentMs = millis(); | |
return; | |
} | |
uint32_t ms = millis(); | |
if (now || ms < sentMs || (ms - sentMs) > 30000) { | |
sentPosition = position; | |
sentMs = 0; | |
// Store (and autosend) at most every 30 seconds (so we'll probably | |
// store once every move) | |
EEPROM.write(EEPROM_POSITION, sentPosition >> 8); | |
EEPROM.write(EEPROM_POSITION+1, sentPosition & 0xFF); | |
serialWrite('P'); | |
serialWrite((sentPosition>>8)&0xFF); | |
serialWrite(sentPosition&0xFF); | |
serialFlush(); | |
} | |
} | |
void loop(){ | |
storePosition(false); | |
if (target == 0) { | |
digitalWrite(UP_PIN, LOW); | |
digitalWrite(DOWN_PIN, LOW); | |
} else { | |
if (target > position) { | |
if (targetUp) { | |
digitalWrite(UP_PIN, HIGH); | |
digitalWrite(DOWN_PIN, LOW); | |
} else { | |
target = 0; | |
} | |
} else if (target < position) { | |
if (targetUp) { | |
target = 0; | |
} else { | |
digitalWrite(UP_PIN, LOW); | |
digitalWrite(DOWN_PIN, HIGH); | |
} | |
} else { | |
digitalWrite(UP_PIN, LOW); | |
digitalWrite(DOWN_PIN, LOW); | |
} | |
} | |
if (Serial1.available() > 0) { | |
uint8_t u8_0, u8_1, u8_2, u8_3; | |
uint16_t u16_0, u16_1; | |
byte cmd = serialRead(); | |
switch (cmd) { | |
case 'E': | |
u16_0 = ((uint16_t) serialRead()) << 8; | |
u16_0 |= (uint16_t) serialRead(); | |
serialWrite('e'); | |
serialWrite(EEPROM.read(u16_0)); | |
serialFlush(); | |
break; | |
case 'G': | |
target = (((uint16_t) serialRead()) << 8) | ((uint16_t) serialRead()); | |
if (EEPROM.read(EEPROM_CURRENT_POS) != 255) | |
EEPROM.write(EEPROM_CURRENT_POS, 255); | |
targetUp = false; | |
if (target > position) | |
targetUp = true; | |
if (target == position) | |
target = 0; | |
break; | |
case 'I': | |
serialWrite('k'); | |
serialWrite('s'); | |
serialWrite('e'); | |
serialWrite('D'); | |
serialWrite(KSED_VERSION); | |
serialFlush(); | |
break; | |
case 'M': | |
u8_0 = serialRead(); | |
if (u8_0 > 2) break; // TODO: configure number of stored positions? | |
u16_0 = EEPROM.read(EEPROM_CURRENT_USER); | |
if (u16_0 == 255) break; | |
u16_0 = EEPROM_USERS_OFFSET + (u16_0 * EEPROM_USER_LENGTH); | |
u16_1 = EEPROM.read(u16_0 + (u8_0*2)); | |
if (u16_1 == 255) break; | |
target = u16_1 << 8; | |
target |= EEPROM.read(u16_0 + (u8_0*2) + 1); | |
targetUp = false; | |
if (target > position) | |
targetUp = true; | |
if (target == position) | |
target = 0; | |
break; | |
EEPROM.write(EEPROM_CURRENT_POS, u8_0); | |
break; | |
case 'P': | |
u16_0 = position; | |
serialWrite('p'); | |
serialWrite(u16_0>>8); | |
serialWrite(u16_0&0xFF); | |
serialFlush(); | |
break; | |
case 'S': | |
u8_0 = serialRead(); // pos | |
u8_1 = serialRead(); // upper | |
u8_2 = serialRead(); // lower | |
u8_3 = EEPROM.read(EEPROM_CURRENT_USER); | |
if (u8_0 > 2) break; // TODO: configure number of stored positions? | |
if (u8_3 == 255) break; | |
u16_0 = EEPROM_USERS_OFFSET + (u8_3*EEPROM_USER_LENGTH) + u8_0; | |
EEPROM.write(u16_0, u8_1); | |
EEPROM.write(u16_0+1, u8_2); | |
break; | |
case 'T': | |
serialWrite('t'); | |
serialWrite(target>>8); | |
serialWrite(target&0xFF); | |
serialFlush(); | |
break; | |
case 'X': | |
u16_0 = serialRead(); | |
EEPROM.write(EEPROM_CURRENT_USER, u16_0); | |
u16_0 = EEPROM_USERS_OFFSET + (u16_0*EEPROM_USER_LENGTH); | |
u8_0 = EEPROM.read(EEPROM_CURRENT_POS); | |
if (u8_0 == 255) break; | |
u16_0 += u8_0 * 2; // TODO: configure number of stored positions? | |
u16_1 = EEPROM.read(u16_0); | |
if (u16_1 == 255) break; | |
target = (u16_1 << 8) | EEPROM.read(u16_0 + 1); | |
targetUp = false; | |
if (target > position) | |
targetUp = true; | |
if (target == position) | |
target = 0; | |
break; | |
break; | |
case 'Z': | |
target = 0x0000; | |
position = 0x1000; | |
// sentPosition = 0x1000; | |
// EEPROM.write(EEPROM_POSITION, 0x10); | |
// EEPROM.write(EEPROM_POSITION+1, 0x00); | |
// sentMs = 0; | |
storePosition(true); | |
break; | |
} | |
} | |
if (nfc && mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) { | |
if (mfrc522.uid.size <= 10) { | |
if (uidSize != mfrc522.uid.size) | |
uidSize = mfrc522.uid.size; | |
for (int i = 0; i < uidSize; i++) { | |
uidByte[i] = mfrc522.uid.uidByte[i]; | |
} | |
serialWrite('C'); | |
serialWrite(uidSize); | |
for (int i = 0; i < uidSize; i++) { | |
serialWrite(uidByte[i]); | |
} | |
} | |
mfrc522.PICC_HaltA(); | |
serialFlush(); | |
} | |
} | |
void updateEncoder(){ | |
uint8_t MSB = digitalRead(ENCODER_PIN1); // MSB = most significant bit | |
uint8_t LSB = digitalRead(ENCODER_PIN2); // LSB = least significant bit | |
uint8_t encoded = (MSB << 1) |LSB; // converting the 2 pin value to single number | |
uint8_t sum = (lastEncoded << 2) | encoded; // adding it to the previous encoded value | |
if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) position ++; | |
if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) position --; | |
lastEncoded = encoded; //store this value for next time | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment