adding CAN Bus BFF examples
Adding Arduino and CircuitPython CAN Bus BFF examples
This commit is contained in:
parent
92898c54a0
commit
17d8ec9437
6 changed files with 352 additions and 0 deletions
|
|
@ -0,0 +1,83 @@
|
|||
// SPDX-FileCopyrightText: 2024 Limor Fried for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <Adafruit_MCP2515.h>
|
||||
#include <Adafruit_SSD1306.h>
|
||||
#include <Fonts/FreeSans9pt7b.h>
|
||||
|
||||
#define CS_PIN A3
|
||||
#define CAN_BAUDRATE (250000)
|
||||
|
||||
Adafruit_MCP2515 mcp(CS_PIN);
|
||||
Adafruit_SSD1306 oled(128, 64, &Wire1, -1);
|
||||
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while(!Serial) delay(10);
|
||||
Serial.println("MCP2515 OLED Receiver test!");
|
||||
|
||||
if (!mcp.begin(CAN_BAUDRATE)) {
|
||||
Serial.println("Error initializing MCP2515.");
|
||||
while(1) delay(10);
|
||||
}
|
||||
Serial.println("MCP2515 chip found");
|
||||
|
||||
if (!oled.begin(SSD1306_SWITCHCAPVCC, 0x3D)) {
|
||||
Serial.println(F("SSD1306 allocation failed"));
|
||||
while(1) delay(10);
|
||||
}
|
||||
oled.display();
|
||||
delay(1000);
|
||||
oled.clearDisplay();
|
||||
oled.display();
|
||||
oled.setFont(&FreeSans9pt7b);
|
||||
oled.setTextColor(SSD1306_WHITE);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// try to parse packet
|
||||
int packetSize = mcp.parsePacket();
|
||||
|
||||
if (packetSize) {
|
||||
// received a packet
|
||||
Serial.print("Received ");
|
||||
|
||||
|
||||
Serial.print("packet with id 0x");
|
||||
Serial.print(mcp.packetId(), HEX);
|
||||
Serial.print(" and length ");
|
||||
Serial.println(packetSize);
|
||||
|
||||
// only look for correct length packets
|
||||
if (packetSize != 3) return;
|
||||
|
||||
// wait till all data is ready!
|
||||
while (mcp.available() != 3) {
|
||||
delay(1);
|
||||
}
|
||||
uint8_t button_state = 0;
|
||||
int16_t val = 0;
|
||||
|
||||
button_state = mcp.read();
|
||||
val = mcp.read();
|
||||
val <<= 8;
|
||||
val |= mcp.read();
|
||||
|
||||
Serial.print("Button is ");
|
||||
if (button_state) Serial.print("pressed");
|
||||
else Serial.print("released");
|
||||
Serial.print(" & value is ");
|
||||
Serial.println(val);
|
||||
|
||||
oled.clearDisplay();
|
||||
oled.setCursor(0, 15);
|
||||
oled.println("CAN receiver");
|
||||
oled.print("Val: "); oled.println(val);
|
||||
oled.print("Button ");
|
||||
if (button_state) oled.print("DOWN");
|
||||
else oled.print("UP");
|
||||
oled.display();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
// SPDX-FileCopyrightText: 2024 Limor Fried for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "Adafruit_seesaw.h"
|
||||
#include <seesaw_neopixel.h>
|
||||
#include <Adafruit_MCP2515.h>
|
||||
#include <Adafruit_NeoPixel.h>
|
||||
|
||||
|
||||
#define CS_PIN PIN_CAN_CS // for Feather RP2040 CAN, change if needed!
|
||||
Adafruit_MCP2515 mcp(CS_PIN);
|
||||
|
||||
|
||||
#define CAN_BAUDRATE (250000) // must match the other devices!
|
||||
#define SS_SWITCH 24
|
||||
#define SS_NEOPIX 6
|
||||
#define SEESAW_ADDR 0x36
|
||||
|
||||
Adafruit_seesaw ss;
|
||||
seesaw_NeoPixel sspixel = seesaw_NeoPixel(1, SS_NEOPIX, NEO_GRB + NEO_KHZ800);
|
||||
Adafruit_NeoPixel pixel(1, 21, NEO_GRB + NEO_KHZ800);
|
||||
|
||||
|
||||
int16_t encoder_position;
|
||||
bool button_state;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(500);
|
||||
while (!Serial) delay(10);
|
||||
|
||||
Serial.println("MCP2515 Sender test!");
|
||||
if (!mcp.begin(CAN_BAUDRATE)) {
|
||||
Serial.println("Error initializing MCP2515.");
|
||||
while(1) delay(10);
|
||||
}
|
||||
Serial.println("MCP2515 chip found");
|
||||
|
||||
Serial.println("Looking for seesaw!");
|
||||
if (! ss.begin(SEESAW_ADDR) || ! sspixel.begin(SEESAW_ADDR)) {
|
||||
Serial.println("Couldn't find seesaw on default address");
|
||||
while(1) delay(10);
|
||||
}
|
||||
Serial.println("seesaw started");
|
||||
|
||||
uint32_t version = ((ss.getVersion() >> 16) & 0xFFFF);
|
||||
if (version != 4991){
|
||||
Serial.print("Wrong firmware loaded? ");
|
||||
Serial.println(version);
|
||||
while(1) delay(10);
|
||||
}
|
||||
Serial.println("Found Product 4991");
|
||||
|
||||
// set not so bright!
|
||||
sspixel.setBrightness(20);
|
||||
sspixel.show();
|
||||
|
||||
// ditto built in pixel
|
||||
pinMode(NEOPIXEL_POWER, OUTPUT);
|
||||
digitalWrite(NEOPIXEL_POWER, HIGH);
|
||||
pixel.begin();
|
||||
pixel.setBrightness(20);
|
||||
pixel.show();
|
||||
|
||||
// use a pin for the built in encoder switch
|
||||
ss.pinMode(SS_SWITCH, INPUT_PULLUP);
|
||||
|
||||
// get starting position
|
||||
encoder_position = ss.getEncoderPosition();
|
||||
button_state = ss.digitalRead(SS_SWITCH);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
bool new_button = ss.digitalRead(SS_SWITCH);
|
||||
|
||||
if (new_button != button_state) {
|
||||
Serial.println("Button pressed!");
|
||||
}
|
||||
|
||||
int32_t new_position = ss.getEncoderPosition();
|
||||
// did we move around or button change?
|
||||
if ((new_button != button_state) ||
|
||||
(encoder_position != new_position)) {
|
||||
|
||||
encoder_position = new_position; // and save for next round
|
||||
button_state = new_button;
|
||||
|
||||
pixel.setPixelColor(0, Wheel(new_position & 0xFF));
|
||||
pixel.show();
|
||||
|
||||
Serial.print("Sending Position ");
|
||||
Serial.print(encoder_position);
|
||||
Serial.print(" & Button ");
|
||||
Serial.println(button_state);
|
||||
|
||||
mcp.beginPacket(0x12);
|
||||
if (ss.digitalRead(SS_SWITCH)) {
|
||||
mcp.write(0);
|
||||
} else {
|
||||
mcp.write(1);
|
||||
}
|
||||
mcp.write(encoder_position >> 8);
|
||||
mcp.write(encoder_position & 0xFF);
|
||||
if (mcp.endPacket()) {
|
||||
Serial.println("Done");
|
||||
// change the neopixel color on success
|
||||
sspixel.setPixelColor(0, Wheel(new_position & 0xFF));
|
||||
} else {
|
||||
Serial.println("Failure");
|
||||
// turn off neopixel on failure
|
||||
sspixel.setPixelColor(0, 0x00);
|
||||
}
|
||||
sspixel.show();
|
||||
}
|
||||
|
||||
// don't overwhelm serial port
|
||||
delay(10);
|
||||
}
|
||||
|
||||
|
||||
uint32_t Wheel(byte WheelPos) {
|
||||
WheelPos = 255 - WheelPos;
|
||||
if (WheelPos < 85) {
|
||||
return sspixel.Color(255 - WheelPos * 3, 0, WheelPos * 3);
|
||||
}
|
||||
if (WheelPos < 170) {
|
||||
WheelPos -= 85;
|
||||
return sspixel.Color(0, WheelPos * 3, 255 - WheelPos * 3);
|
||||
}
|
||||
WheelPos -= 170;
|
||||
return sspixel.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
|
||||
}
|
||||
66
CAN_Bus_BFF/CircuitPython/can_bus_bff_receiver.py
Normal file
66
CAN_Bus_BFF/CircuitPython/can_bus_bff_receiver.py
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
# SPDX-FileCopyrightText: 2024 ladyada for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
import time
|
||||
import board
|
||||
import terminalio
|
||||
import displayio
|
||||
from digitalio import DigitalInOut
|
||||
from adafruit_mcp2515.canio import Message, RemoteTransmissionRequest
|
||||
from adafruit_mcp2515 import MCP2515 as CAN
|
||||
import adafruit_displayio_ssd1306
|
||||
from adafruit_display_text import label
|
||||
|
||||
displayio.release_displays()
|
||||
|
||||
i2c = board.STEMMA_I2C()
|
||||
# STEMMA OLED setup
|
||||
display_bus = displayio.I2CDisplay(i2c, device_address=0x3D, reset=None)
|
||||
display = adafruit_displayio_ssd1306.SSD1306(display_bus, width=128, height=64)
|
||||
|
||||
cs = DigitalInOut(board.A3)
|
||||
cs.switch_to_output()
|
||||
spi = board.SPI()
|
||||
|
||||
can_bus = CAN(
|
||||
spi, cs, loopback=False, silent=False
|
||||
) # use loopback to test without another device
|
||||
|
||||
splash = displayio.Group()
|
||||
display.root_group = splash
|
||||
|
||||
font = terminalio.FONT
|
||||
main_area = label.Label(
|
||||
font, text="CAN Receiver", color=0xFFFFFF)
|
||||
main_area.anchor_point = (0.5, 0.0)
|
||||
main_area.anchored_position = (display.width / 2, 0)
|
||||
|
||||
msg_area = label.Label(
|
||||
font, text="ID: ", color=0xFFFFFF)
|
||||
msg_area.anchor_point = (0.0, 0.5)
|
||||
msg_area.anchored_position = (0, display.height / 2)
|
||||
|
||||
val_area = label.Label(
|
||||
font, text="Val: ", color=0xFFFFFF)
|
||||
val_area.anchor_point = (0.0, 1.0)
|
||||
val_area.anchored_position = (0, display.height)
|
||||
|
||||
splash.append(main_area)
|
||||
splash.append(msg_area)
|
||||
splash.append(val_area)
|
||||
|
||||
while True:
|
||||
with can_bus.listen(timeout=1.0) as listener:
|
||||
|
||||
message_count = listener.in_waiting()
|
||||
for i in range(message_count):
|
||||
print(message_count, "messages available")
|
||||
msg = listener.receive()
|
||||
print("Message from ", hex(msg.id))
|
||||
msg_area.text = f"ID: {hex(msg.id)}"
|
||||
if isinstance(msg, Message):
|
||||
print("message data:", msg.data)
|
||||
val_area.text = f"Val: {msg.data}"
|
||||
if isinstance(msg, RemoteTransmissionRequest):
|
||||
print("RTR length:", msg.length)
|
||||
time.sleep(0.1)
|
||||
70
CAN_Bus_BFF/CircuitPython/can_bus_feather_send.py
Normal file
70
CAN_Bus_BFF/CircuitPython/can_bus_feather_send.py
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
# SPDX-FileCopyrightText: Copyright (c) 2024 ladyada for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
import time
|
||||
import board
|
||||
from rainbowio import colorwheel
|
||||
from digitalio import DigitalInOut
|
||||
from adafruit_mcp2515 import MCP2515 as CAN
|
||||
from adafruit_mcp2515.canio import Message
|
||||
from adafruit_seesaw import seesaw, neopixel, rotaryio, digitalio
|
||||
|
||||
cs = DigitalInOut(board.CAN_CS)
|
||||
cs.switch_to_output()
|
||||
spi = board.SPI()
|
||||
|
||||
can_bus = CAN(
|
||||
spi, cs, loopback=False, silent=False
|
||||
) # use loopback to test without another device
|
||||
|
||||
i2c = board.I2C() # uses board.SCL and board.SDA
|
||||
# i2c = board.STEMMA_I2C() # For using the built-in STEMMA QT connector on a microcontroller
|
||||
seesaw = seesaw.Seesaw(i2c, addr=0x36)
|
||||
|
||||
seesaw_product = (seesaw.get_version() >> 16) & 0xFFFF
|
||||
print("Found product {}".format(seesaw_product))
|
||||
if seesaw_product != 4991:
|
||||
print("Wrong firmware loaded? Expected 4991")
|
||||
|
||||
seesaw.pin_mode(24, seesaw.INPUT_PULLUP)
|
||||
button = digitalio.DigitalIO(seesaw, 24)
|
||||
pixel = neopixel.NeoPixel(seesaw, 6, 1)
|
||||
pixel.brightness = 0.3
|
||||
|
||||
button_held = False
|
||||
color = 0
|
||||
|
||||
encoder = rotaryio.IncrementalEncoder(seesaw)
|
||||
last_position = 0
|
||||
|
||||
while True:
|
||||
with can_bus.listen(timeout=5.0) as listener:
|
||||
position = -encoder.position
|
||||
|
||||
if position != last_position:
|
||||
if position > last_position:
|
||||
color += 5
|
||||
else:
|
||||
color -= 5
|
||||
color = (color + 256) % 256 # wrap around to 0-256
|
||||
pixel.fill(colorwheel(color))
|
||||
last_position = position
|
||||
str_pos = str(position)
|
||||
byte_pos = str_pos.encode()
|
||||
message = Message(id=0x1234ABCD, data=byte_pos, extended=True)
|
||||
send_success = can_bus.send(message)
|
||||
print("Send success:", send_success)
|
||||
|
||||
if not button.value and not button_held:
|
||||
button_held = True
|
||||
message = Message(id=0x1234ABCD, data=b"pressed", extended=True)
|
||||
send_success = can_bus.send(message)
|
||||
print("Send success:", send_success)
|
||||
|
||||
if button.value and button_held:
|
||||
button_held = False
|
||||
message = Message(id=0x1234ABCD, data=b"released", extended=True)
|
||||
send_success = can_bus.send(message)
|
||||
print("Send success:", send_success)
|
||||
|
||||
time.sleep(0.1)
|
||||
Loading…
Reference in a new issue