yes sure !
This is the code for the RPM and RaceCar style Shift Light :
The Shift Light is for testing (I have a stock car).
However, I have an issue with my car's water temperature. Even though I have replaced many parts, the problem still persists.
While working on the temperature monitor, I also worked on the shift light because why not! XD
I hope this code helps car guys with their future car projects.
#include <SPI.h>
#include <CAN.h>
#include <Wire.h>
#include <Adafruit_NeoPixel.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define OLED_RESET -1 // Reset pin (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C // Most common I2C address for SSD1306
const int SPI_CS_PIN = 10;
const int INT_PIN = 2;
const int LED_PIN = 6; // Pin where the NeoPixel is connected
const int NUM_LEDS = 8; // Number of LEDs in the strip
int MaxRpm = 5000;
char rpmStr[6]; // Smaller buffer, RPM values won't exceed 5 characters plus null terminator
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
const uint32_t RED = strip.Color(255, 0, 0);
const uint32_t colorPattern[NUM_LEDS] = {
strip.Color(0, 0, 255), // Blue
strip.Color(255, 0, 255), // Purple
strip.Color(255, 0, 255), // Purple
strip.Color(255, 0, 0), // Red
strip.Color(255, 0, 0), // Red
strip.Color(255, 0, 255), // Purple
strip.Color(255, 0, 255), // Purple
strip.Color(0, 0, 255) // Blue
};
void setup() {
Serial.begin(115200);
strip.begin();
strip.show();
while (!Serial)
;
Serial.println(F("CAN Receiver")); // Store string in flash memory
// Start the CAN bus at 500 kbps
if (!CAN.begin(500E3)) {
Serial.println(F("Starting CAN failed!"));
while (1)
;
}
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;)
;
}
display.clearDisplay();
display.setTextSize(3); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(2, 10);
display.print(F("SKYSPEC")); // Print static string from flash
display.display();
}
void loop() {
static unsigned long lastFlashTime = 0;
static bool flashState = false;
int packetSize = CAN.parsePacket();
if (packetSize) {
unsigned long packetId = CAN.packetId();
if (packetId == 0x1c1) {
Serial.print(F("Received packet with id 0x"));
Serial.println(packetId, HEX);
byte buf[8];
int len = 0;
while (CAN.available() && len < 8) {
buf[len++] = CAN.read();
}
int RPM = buf[2] * 256 + buf[3];
Serial.println(RPM);
// Display RPM on OLED
itoa(RPM, rpmStr, 10);
display.clearDisplay();
display.setTextSize(2); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(12, 12);
display.print(F("RPM: ")); // Print static string from flash
display.print(rpmStr); // Print the RPM value
display.display();
// Update NeoPixels
strip.clear();
if (RPM > MaxRpm) {
// Flash all LEDs red
unsigned long currentTime = millis();
if (currentTime - lastFlashTime >= 50) { // Change the flash interval as needed
flashState = !flashState;
lastFlashTime = currentTime;
}
uint32_t color = flashState ? RED : strip.Color(0, 0, 0); // Toggle between red and off
for (int i = 0; i < NUM_LEDS; i++) {
strip.setPixelColor(i, color);
}
} else if (RPM >= 2300 && RPM <= MaxRpm) {
// Calculate which LEDs to light up based on RPM
int ledIndex = map(RPM, 2300, MaxRpm, 0, (NUM_LEDS / 2) - 1);
// Update LEDs based on RPM
for (int i = 0; i <= ledIndex; i++) {
strip.setPixelColor(i, colorPattern[i]); // Set the color from the pattern (beginning)
strip.setPixelColor(NUM_LEDS - 1 - i, colorPattern[i]); // Set the color from the pattern (end)
}
}
strip.show();
}
}
}