Skip to content

Instantly share code, notes, and snippets.

@arduinoboard
Last active March 28, 2018 20:52
Show Gist options
  • Save arduinoboard/974e9fcc0b7a867a4466fa29191d56c0 to your computer and use it in GitHub Desktop.
Save arduinoboard/974e9fcc0b7a867a4466fa29191d56c0 to your computer and use it in GitHub Desktop.
The file that is currently on an Arduino/Genuino Mega or Mega 2560 with a serial number of 95336333635351516191
/*----------------------------------
PROGENITOR Sabertooth Steering Wheel
------------------------------------*/
// INCLUSIONS
//-------------------------------------------
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
// DEFINITIONS
//-------------------------------------------
//#define DEBUG
#define TEST
// CONSTANTS
//-------------------------------------------
#define BTN_DEBOUNCE_TIME 50
#define CRUISE_TRANSMIT_PERIOD 100 //time between cruise light sends (ms)
#define BUTTON_REPEAT_HOLD_TIME 600 //press this long (ms) until repeating starts
#define BUTTON_REPEAT_FREQUENCY 100 //repeat key press on this interval (ms)
#define MEDIA_LED_BRIGHTNESS 100 //PWM for media icon light
#define RING_LED_BRIGHTNESS 75 //PWM for joystick ring light
#define CAT_LED_BRIGHTNESS 100 //PWM for category icon light
#define BUTTON_LED_BRIGHTNESS 255 //PWM for button light
#define CRUISE_STRIP_INTENSITY 255
#define CRUISE_STRIP_DELAY 50
#define BUTTON_REPEAT_FREQUENCY 100 //repeat key press on this interval (ms)
#define HEARTBEAT_PERIOD 1000 //send heartbeat once/second
#define NUMPIXELS 85
// VARIABLES
//-------------------------------------------
unsigned long voiceDB = millis();
unsigned long viewDB = millis();
unsigned long spleetUpDB = millis();
unsigned long spleetDownDB = millis();
unsigned long spleetLeftDB = millis();
unsigned long spleetRightDB = millis();
unsigned long mediaVolumeUpDB = millis();
unsigned long mediaVolumeDownDB = millis();
unsigned long mediaNextDB = millis();
unsigned long mediaPrevDB = millis();
unsigned long cruiseDB = millis();
unsigned long cruiseLightsDB = millis();
unsigned long heartbeatDB = millis();
boolean voiceP = false;
boolean viewP = false;
boolean spleetUpP = false;
boolean spleetDownP = false;
boolean spleetLeftP = false;
boolean spleetRightP = false;
boolean mediaVolumeUpP = false;
boolean mediaVolumeDownP = false;
boolean mediaNextP = false;
boolean mediaPrevP = false;
boolean cruiseActiveP = false;
boolean cruiseSetP = false;
boolean cruiseGapToggleP = false;
boolean cruiseCancelResumeP = false;
boolean cruiseUpP = false;
boolean cruiseDownP = false;
boolean cruiseActiveButton = false;
boolean cruiseSetButton = false;
boolean cruiseGapToggle = false;
boolean cruiseCancelResumeButton = false;
boolean cruiseUpButton = false;
boolean cruiseDownButton = false;
String m_cruiseState = "off";
String m_menuState = "closed";
String m_ignitionState = "1";
int repeat;
int leftCruiseLights = 2;
int rightCruiseLights = 0;
// INPUTS
//-------------------------------------------
#define VOICE_BTN 22
#define VIEW_BTN 46
#define SPLEET_UP_BTN 34
#define SPLEET_DOWN_BTN 30
#define SPLEET_LEFT_BTN 48
#define SPLEET_RIGHT_BTN 32
#define MEDIA_VOLUME_UP_BTN 24
#define MEDIA_VOLUME_DOWN_BTN 40
#define MEDIA_NEXT_BTN 42
#define MEDIA_PREV_BTN 26
#define LEDSTRIP A0
// OUTPUTS
//-------------------------------------------
#define MEDIA_ICONS_LED 5
#define JOYSTICK_RING_LED 3
#define CATEGORY_LED 6
#define BUTTON_LEDS 2
// SETUP
//-------------------------------------------
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, LEDSTRIP, NEO_RGBW + NEO_KHZ800);
void setup()
{
pixels.begin(); // This initializes the NeoPixel library.
pinMode(VOICE_BTN, INPUT);
pinMode(VIEW_BTN, INPUT);
pinMode(SPLEET_UP_BTN, INPUT);
pinMode(SPLEET_DOWN_BTN, INPUT);
pinMode(SPLEET_LEFT_BTN, INPUT);
pinMode(SPLEET_RIGHT_BTN, INPUT);
pinMode(MEDIA_VOLUME_UP_BTN, INPUT);
pinMode(MEDIA_VOLUME_DOWN_BTN, INPUT);
pinMode(MEDIA_NEXT_BTN, INPUT);
pinMode(MEDIA_PREV_BTN, INPUT);
pinMode(MEDIA_ICONS_LED, OUTPUT); //on left
pinMode(JOYSTICK_RING_LED, OUTPUT);//on right
pinMode(CATEGORY_LED, OUTPUT); //icons on right
pinMode(BUTTON_LEDS, OUTPUT); //microphone and view leds?
digitalWrite(VOICE_BTN, HIGH);
digitalWrite(VIEW_BTN, HIGH);
digitalWrite(SPLEET_UP_BTN, HIGH);
digitalWrite(SPLEET_DOWN_BTN, HIGH);
digitalWrite(SPLEET_LEFT_BTN, HIGH);
digitalWrite(SPLEET_RIGHT_BTN, HIGH);
digitalWrite(MEDIA_VOLUME_UP_BTN, HIGH);
digitalWrite(MEDIA_VOLUME_DOWN_BTN, HIGH);
digitalWrite(MEDIA_PREV_BTN, HIGH);
digitalWrite(MEDIA_NEXT_BTN, HIGH);
analogWrite(MEDIA_ICONS_LED, MEDIA_LED_BRIGHTNESS);
analogWrite(JOYSTICK_RING_LED, 0);
analogWrite(CATEGORY_LED, CAT_LED_BRIGHTNESS);
analogWrite(BUTTON_LEDS, BUTTON_LED_BRIGHTNESS);
Serial.begin(115200);
#ifdef DEBUG
Serial.println("I'm alive");
#endif
Serial2.begin(9600);
Serial3.begin(9600);
initLeftCruise();
initRightCruise();
steeringWheelLightOff();
}
// LOOP
//-------------------------------------------
void loop()
{
while(Serial.available()){
int command = Serial.read();
/*
command
1 ---- all lights off
2 ---- category mode
3 ---- spleet mode
4 ---- cruise off
5 ---- cruise unset
6 ---- cruise set
7 ---- cruise cancel
*/
switch (command) {
case '0':
#ifdef DEBUG
Serial.println("All lights off");
#endif
analogWrite(MEDIA_ICONS_LED, 0);
analogWrite(JOYSTICK_RING_LED, 0);
analogWrite(CATEGORY_LED, 0);
analogWrite(BUTTON_LEDS, 0);
leftCruiseLights = 0;
rightCruiseLights = 0;
steeringWheelLightOff();
break;
case '1':
#ifdef DEBUG
Serial.println("Turning on Cat");
#endif
analogWrite(MEDIA_ICONS_LED, MEDIA_LED_BRIGHTNESS);
analogWrite(JOYSTICK_RING_LED, 0);
analogWrite(CATEGORY_LED, CAT_LED_BRIGHTNESS);
analogWrite(BUTTON_LEDS, BUTTON_LED_BRIGHTNESS);
break;
case '2':
#ifdef DEBUG
Serial.println("Turning On Spleet");
#endif
analogWrite(MEDIA_ICONS_LED, MEDIA_LED_BRIGHTNESS);
analogWrite(JOYSTICK_RING_LED, RING_LED_BRIGHTNESS);
analogWrite(CATEGORY_LED, 0);
analogWrite(BUTTON_LEDS, BUTTON_LED_BRIGHTNESS);
break;
case '3':
#ifdef DEBUG
Serial.println("Turning Cruise Off");
#endif
leftCruiseLights = 2;
rightCruiseLights = 0;
break;
case '4':
#ifdef DEBUG
Serial.println("Turning Cruise Unset");
#endif
leftCruiseLights = 10;
rightCruiseLights = 0;
steeringWheelLightOff(); //we only test cruise with blue zone
break;
case '5':
#ifdef DEBUG
Serial.println("Turning Cruise Set");
#endif
leftCruiseLights = 14;
rightCruiseLights = 14;
steeringWheelLightFullBlue(); //we only test cruise with blue zone
break;
case '6':
#ifdef DEBUG
Serial.println("Turning Cruise Canceled");
#endif
leftCruiseLights = 14;
rightCruiseLights = 13;
break;
case '7':
#ifdef DEBUG
Serial.println("Going to the Blue Zone");
#endif
steeringWheelLightFullBlue();
break;
case '8':
#ifdef DEBUG
Serial.println("Going to the Yellow Zone");
#endif
steeringWheelLightYellowHands();
break;
case '9':
#ifdef DEBUG
Serial.println("Going to the Red Zone");
#endif
steeringWheelLightRedHandsFlash();
break;
case 'z':
#ifdef DEBUG
Serial.println("No steering LED");
#endif
steeringWheelLightOff();
break;
case 'l':
#ifdef DEBUG
Serial.println("Left Turn");
#endif
steeringWheelBlueLeft();
break;
case 'r':
#ifdef DEBUG
Serial.println("Right Turn");
#endif
steeringWheelBlueRight();
break;
case 'g':
#ifdef DEBUG
Serial.println("Going Green");
#endif
steeringWheelLightGreen();
break;
}
}
if(m_ignitionState == "1") {
checkForButtonEvent(viewDB, viewP, digitalRead(VIEW_BTN), "viewButton");
checkForButtonEvent(voiceDB, voiceP, digitalRead(VOICE_BTN), "voiceButton");
checkForButtonEvent(spleetUpDB, spleetUpP, digitalRead(SPLEET_UP_BTN), "spleetUpButton");
checkForButtonEvent(spleetDownDB, spleetDownP, digitalRead(SPLEET_DOWN_BTN), "spleetDownButton");
checkForButtonEvent(spleetLeftDB, spleetLeftP, digitalRead(SPLEET_LEFT_BTN), "spleetLeftButton");
checkForButtonEvent(spleetRightDB, spleetRightP, digitalRead(SPLEET_RIGHT_BTN), "spleetRightButton");
checkForRepeatButtonEvent(mediaVolumeDownDB, mediaVolumeDownP, digitalRead(MEDIA_VOLUME_DOWN_BTN), "mediaDownButton");
checkForRepeatButtonEvent(mediaVolumeUpDB, mediaVolumeUpP, digitalRead(MEDIA_VOLUME_UP_BTN), "mediaUpButton");
checkForRepeatButtonEvent(mediaPrevDB, mediaPrevP, digitalRead(MEDIA_PREV_BTN), "mediaPrevButton");
checkForRepeatButtonEvent(mediaNextDB, mediaNextP, digitalRead(MEDIA_NEXT_BTN), "mediaNextButton");
checkLeftCruise();
checkRightCruise();
checkForCanButtonEvent(cruiseDB, cruiseActiveP, !cruiseActiveButton, "cruiseActiveButton");
checkForCanButtonEvent(cruiseDB, cruiseSetP, !cruiseSetButton, "cruiseSetButton");
checkForCanButtonEvent(cruiseDB, cruiseCancelResumeP, !cruiseCancelResumeButton, "cruiseCancelResumeButton");
if (m_cruiseState != "unset"){ //if cruise is unset don't allow adjustment buttons to be pressed
checkForCanButtonEvent(cruiseDB, cruiseUpP, !cruiseUpButton, "cruiseUpButton");
checkForCanButtonEvent(cruiseDB, cruiseDownP, !cruiseDownButton, "cruiseDownButton");
checkForCanButtonEvent(cruiseDB, cruiseGapToggleP, !cruiseGapToggle, "cruiseGapToggle");
}
}
updateCruiseLEDs(cruiseLightsDB);
}
void buttonEventComms(char* eventName){
if(eventName=="mediaUpButton"){
Serial.print("a");
}else if(eventName=="mediaDownButton"){
Serial.print("b");
}else if(eventName=="mediaPrevButton"){
Serial.print("c");
}else if(eventName=="mediaNextButton"){
Serial.print("d");
}else if(eventName=="spleetUpButton"){
Serial.print("e");
}else if(eventName=="spleetDownButton"){
Serial.print("f");
}else if(eventName=="spleetLeftButton"){
Serial.print("g");
}else if(eventName=="spleetRightButton"){
Serial.print("h");
}else if(eventName=="voiceButton"){
Serial.print("i");
}else if(eventName=="viewButton"){
Serial.print("j");
}
}
void checkForButtonEvent(unsigned long& lastTime, boolean& wasPressed, boolean isUp, char* eventName) {
if (millis() - BTN_DEBOUNCE_TIME > lastTime) {
if(!wasPressed && !isUp){
#ifdef DEBUG
Serial.println(eventName);
#endif
buttonEventComms(eventName);
wasPressed = true;
lastTime = millis();
}
if(wasPressed && isUp){
wasPressed = false;
lastTime = millis();
}
}
}
//-----------------------------------------------
//send both true when pressed and false when unpressed values for communication with the car
void checkForCanButtonEvent(unsigned long& lastTime, boolean& wasPressed, boolean isUp, char* eventName) {
if (millis() - BTN_DEBOUNCE_TIME > lastTime) {
//
if(!wasPressed && !isUp){
#ifdef DEBUG
Serial.print(eventName);
Serial.println(" - on");
#endif
if(eventName=="cruiseActiveButton"){
Serial.print("k");
}else if(eventName=="cruiseSetButton"){
Serial.print("l");
}else if(eventName=="cruiseGapToggle"){
Serial.print("m");
}else if(eventName=="cruiseCancelResumeButton"){
Serial.print("n");
}else if(eventName=="cruiseUpButton"){
Serial.print("o");
}else if(eventName=="cruiseDownButton"){
Serial.print("p");
}
wasPressed = true;
lastTime = millis();
}
if(wasPressed && isUp){
#ifdef DEBUG
Serial.print(eventName);
Serial.println(" - off");
#endif
if(eventName=="cruiseActiveButton"){
Serial.print("K");
}else if(eventName=="cruiseSetButton"){
Serial.print("L");
}else if(eventName=="cruiseGapToggle"){
Serial.print("M");
}else if(eventName=="cruiseCancelResumeButton"){
Serial.print("N");
}else if(eventName=="cruiseUpButton"){
Serial.print("O");
}else if(eventName=="cruiseDownButton"){
Serial.print("P");
}
wasPressed = false;
lastTime = millis();
}
}
}
//-----------------------------------------------
//sends a true event when pressed and repeating true events when held (no false events)
void checkForRepeatButtonEvent(unsigned long& lastTime, boolean& wasPressed, boolean isUp, char* eventName) {
if (millis() - BTN_DEBOUNCE_TIME > lastTime) {
//
if(!wasPressed && !isUp){
#ifdef DEBUG
Serial.println(eventName);
#endif
buttonEventComms(eventName);
wasPressed = true;
lastTime = millis();
repeat = BUTTON_REPEAT_HOLD_TIME;
}
if(wasPressed && !isUp){ //repeat if held down
if(millis() - repeat > lastTime) {
#ifdef DEBUG
Serial.println(eventName);
#endif
buttonEventComms(eventName);
lastTime = millis();
repeat = BUTTON_REPEAT_FREQUENCY; //repeating every 100ms
}
}
if(wasPressed && isUp){
wasPressed = false;
lastTime = millis();
}
}
}
void steeringWheelLightFullBlue(){
for(int i=0;i<NUMPIXELS;i++){
int brightness=(NUMPIXELS-(i*2));
if(brightness<0){
brightness=0;
}
if(i%2==0){
pixels.setPixelColor((NUMPIXELS/2)+(i/2), pixels.Color(0,0,brightness,0));
}else{
pixels.setPixelColor((NUMPIXELS/2)-(i/2)-1, pixels.Color(0,0,brightness,0));
}
pixels.show(); // This sends the updated pixel color to the hardware.
}
}
void steeringWheelLightGreen(){
for(int i=0;i<NUMPIXELS;i++){
int brightness=(NUMPIXELS-(i*2));
if(brightness<0){
brightness=0;
}
if(i%2==0){
pixels.setPixelColor((NUMPIXELS/2)+(i/2), pixels.Color(brightness,0,0,0));
}else{
pixels.setPixelColor((NUMPIXELS/2)-(i/2)-1, pixels.Color(brightness,0,0,0));
}
pixels.show(); // This sends the updated pixel color to the hardware.
}
}
void steeringWheelBlueLeft(){
for(int j=0;j<=25;j++){
for(int i=0;i<NUMPIXELS;i++){
int brightness=(NUMPIXELS-(i*2));
if(brightness<0){
brightness=0;
}
if(i%2==0){
pixels.setPixelColor((NUMPIXELS/2)-j+(i/2), pixels.Color(0,0,brightness,0));
}else{
pixels.setPixelColor((NUMPIXELS/2)-j-(i/2)-1, pixels.Color(0,0,brightness,0));
}
}
pixels.show(); // This sends the updated pixel color to the hardware.
}
delay(2000);
for(int j=25;j>=0;j--){
for(int i=0;i<NUMPIXELS;i++){
int brightness=(NUMPIXELS-(i*2));
if(brightness<0){
brightness=0;
}
if(i%2==0){
pixels.setPixelColor((NUMPIXELS/2)-j+(i/2), pixels.Color(0,0,brightness,0));
}else{
pixels.setPixelColor((NUMPIXELS/2)-j-(i/2)-1, pixels.Color(0,0,brightness,0));
}
}
pixels.show(); // This sends the updated pixel color to the hardware.
delay(20);
}
}
void steeringWheelBlueRight(){
for(int j=0;j<=25;j++){
for(int i=0;i<NUMPIXELS;i++){
int brightness=(NUMPIXELS-(i*2));
if(brightness<0){
brightness=0;
}
if(i%2==0){
pixels.setPixelColor((NUMPIXELS/2)+j+(i/2), pixels.Color(0,0,brightness,0));
}else{
pixels.setPixelColor((NUMPIXELS/2)+j-(i/2)-1, pixels.Color(0,0,brightness,0));
}
}
pixels.show(); // This sends the updated pixel color to the hardware.
}
delay(2000);
for(int j=25;j>=0;j--){
for(int i=0;i<NUMPIXELS;i++){
int brightness=(NUMPIXELS-(i*2));
if(brightness<0){
brightness=0;
}
if(i%2==0){
pixels.setPixelColor((NUMPIXELS/2)+j+(i/2), pixels.Color(0,0,brightness,0));
}else{
pixels.setPixelColor((NUMPIXELS/2)+j-(i/2)-1, pixels.Color(0,0,brightness,0));
}
}
pixels.show(); // This sends the updated pixel color to the hardware.
delay(20);
}
}
void steeringWheelLightYellowHands(){
for(int i=0;i<55;i++){
if(i%2==0){
pixels.setPixelColor((NUMPIXELS/2)+(i/2), pixels.Color(0,0,0,0));
}else{
pixels.setPixelColor((NUMPIXELS/2)-(i/2)-1, pixels.Color(0,0,0,0));
}
}
pixels.show(); // This sends the updated pixel color to the hardware.
for(int i=55;i<NUMPIXELS;i++){
if(i%2==0){
pixels.setPixelColor((NUMPIXELS/2)+(i/2), pixels.Color(150,150,0,0));
}else{
pixels.setPixelColor((NUMPIXELS/2)-(i/2)-1, pixels.Color(150,150,0,0));
}
pixels.show(); // This sends the updated pixel color to the hardware.
}
}
void steeringWheelLightRedHandsFlash(){
steeringWheelLightRedHands();
delay(100);
steeringWheelLightOff();
delay(100);
steeringWheelLightRedHands();
delay(100);
steeringWheelLightOff();
delay(100);
steeringWheelLightRedHands();
delay(100);
}
void steeringWheelLightRedHands(){
for(int i=0;i<15;i++){
pixels.setPixelColor(i, pixels.Color(0,255,0,0));
}
for(int i=NUMPIXELS;i>NUMPIXELS-15;i--){
pixels.setPixelColor(i, pixels.Color(0,255,0,0));
}
pixels.show(); // This sends the updated pixel color to the hardware.
}
void steeringWheelLightOff(){
for(int i=0;i<NUMPIXELS;i++){
pixels.setPixelColor(i, pixels.Color(0,0,0,0));
}
pixels.show(); // This sends the updated pixel color to the hardware.
}
void checkLeftCruise() {
if (Serial2.available()) {
int serial2Byte = Serial2.read();
switch(serial2Byte){
case 0:
cruiseActiveButton = false;
cruiseSetButton = false;
cruiseGapToggle = false;
break;
case 1:
cruiseActiveButton = true;
cruiseSetButton = false;
cruiseGapToggle = false;
break;
case 2:
cruiseActiveButton = false;
cruiseSetButton = true;
cruiseGapToggle = false;
break;
case 3:
cruiseActiveButton = true;
cruiseSetButton = true;
cruiseGapToggle = false;
break;
case 4:
cruiseActiveButton = false;
cruiseSetButton = false;
cruiseGapToggle = true;
break;
case 5:
cruiseActiveButton = true;
cruiseSetButton = false;
cruiseGapToggle = true;
break;
case 6:
cruiseActiveButton = false;
cruiseSetButton = true;
cruiseGapToggle = true;
break;
case 7:
cruiseActiveButton = true;
cruiseSetButton = true;
cruiseGapToggle = true;
break;
case 0x55:
initLeftCruise();
break;
}
}
}
void checkRightCruise() {
if (Serial3.available()) {
int serial3Byte = Serial3.read();
switch(serial3Byte){
case 0:
cruiseCancelResumeButton = false;
cruiseUpButton = false;
cruiseDownButton = false;
break;
case 1:
cruiseCancelResumeButton = true;
cruiseUpButton = false;
cruiseDownButton = false;
break;
case 2:
cruiseCancelResumeButton = false;
cruiseUpButton = true;
cruiseDownButton = false;
break;
case 3:
cruiseCancelResumeButton = true;
cruiseUpButton = true;
cruiseDownButton = false;
break;
case 4:
cruiseCancelResumeButton = false;
cruiseUpButton = false;
cruiseDownButton = true;
break;
case 5:
cruiseCancelResumeButton = true;
cruiseUpButton = false;
cruiseDownButton = true;
break;
case 6:
cruiseCancelResumeButton = false;
cruiseUpButton = true;
cruiseDownButton = true;
break;
case 7:
cruiseCancelResumeButton = true;
cruiseUpButton = true;
cruiseDownButton = true;
break;
case 0x55:
initRightCruise();
break;
}
}
}
void updateCruiseLEDs(unsigned long& lastTime) {
if (millis() - CRUISE_TRANSMIT_PERIOD > lastTime) {
Serial2.write(leftCruiseLights);
Serial3.write(rightCruiseLights);
cruiseLightsDB = millis();
}
}
void initLeftCruise() {
Serial2.write(0x55);
Serial2.write(CRUISE_STRIP_INTENSITY);
Serial2.write(CRUISE_STRIP_DELAY);
Serial2.write(0xAA);
}
void initRightCruise() {
Serial3.write(0x55);
Serial3.write(CRUISE_STRIP_INTENSITY);
Serial3.write(CRUISE_STRIP_DELAY);
Serial3.write(0xAA);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment