From 17d8ec94377d376eddb1cae072d18048ce0c9c63 Mon Sep 17 00:00:00 2001 From: Liz Date: Tue, 30 Jan 2024 17:09:49 -0500 Subject: [PATCH] adding CAN Bus BFF examples Adding Arduino and CircuitPython CAN Bus BFF examples --- .../MCP2515_CAN_BFF_Receive/.none.test.only | 0 .../MCP2515_CAN_BFF_Receive.ino | 83 +++++++++++ .../MCP2515_CAN_Feather_Send/.none.test.only | 0 .../MCP2515_CAN_Feather_Send.ino | 133 ++++++++++++++++++ .../CircuitPython/can_bus_bff_receiver.py | 66 +++++++++ .../CircuitPython/can_bus_feather_send.py | 70 +++++++++ 6 files changed, 352 insertions(+) create mode 100644 CAN_Bus_BFF/Arduino/MCP2515_CAN_BFF_Receive/.none.test.only create mode 100644 CAN_Bus_BFF/Arduino/MCP2515_CAN_BFF_Receive/MCP2515_CAN_BFF_Receive.ino create mode 100644 CAN_Bus_BFF/Arduino/MCP2515_CAN_Feather_Send/.none.test.only create mode 100644 CAN_Bus_BFF/Arduino/MCP2515_CAN_Feather_Send/MCP2515_CAN_Feather_Send.ino create mode 100644 CAN_Bus_BFF/CircuitPython/can_bus_bff_receiver.py create mode 100644 CAN_Bus_BFF/CircuitPython/can_bus_feather_send.py diff --git a/CAN_Bus_BFF/Arduino/MCP2515_CAN_BFF_Receive/.none.test.only b/CAN_Bus_BFF/Arduino/MCP2515_CAN_BFF_Receive/.none.test.only new file mode 100644 index 000000000..e69de29bb diff --git a/CAN_Bus_BFF/Arduino/MCP2515_CAN_BFF_Receive/MCP2515_CAN_BFF_Receive.ino b/CAN_Bus_BFF/Arduino/MCP2515_CAN_BFF_Receive/MCP2515_CAN_BFF_Receive.ino new file mode 100644 index 000000000..475d90398 --- /dev/null +++ b/CAN_Bus_BFF/Arduino/MCP2515_CAN_BFF_Receive/MCP2515_CAN_BFF_Receive.ino @@ -0,0 +1,83 @@ +// SPDX-FileCopyrightText: 2024 Limor Fried for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include +#include +#include + +#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(); + } +} diff --git a/CAN_Bus_BFF/Arduino/MCP2515_CAN_Feather_Send/.none.test.only b/CAN_Bus_BFF/Arduino/MCP2515_CAN_Feather_Send/.none.test.only new file mode 100644 index 000000000..e69de29bb diff --git a/CAN_Bus_BFF/Arduino/MCP2515_CAN_Feather_Send/MCP2515_CAN_Feather_Send.ino b/CAN_Bus_BFF/Arduino/MCP2515_CAN_Feather_Send/MCP2515_CAN_Feather_Send.ino new file mode 100644 index 000000000..44fbe6453 --- /dev/null +++ b/CAN_Bus_BFF/Arduino/MCP2515_CAN_Feather_Send/MCP2515_CAN_Feather_Send.ino @@ -0,0 +1,133 @@ +// SPDX-FileCopyrightText: 2024 Limor Fried for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "Adafruit_seesaw.h" +#include +#include +#include + + +#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); +} diff --git a/CAN_Bus_BFF/CircuitPython/can_bus_bff_receiver.py b/CAN_Bus_BFF/CircuitPython/can_bus_bff_receiver.py new file mode 100644 index 000000000..1adb9c912 --- /dev/null +++ b/CAN_Bus_BFF/CircuitPython/can_bus_bff_receiver.py @@ -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) diff --git a/CAN_Bus_BFF/CircuitPython/can_bus_feather_send.py b/CAN_Bus_BFF/CircuitPython/can_bus_feather_send.py new file mode 100644 index 000000000..f2c2a2788 --- /dev/null +++ b/CAN_Bus_BFF/CircuitPython/can_bus_feather_send.py @@ -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)