Skip to content

Commit 4f5da74

Browse files
author
Stefan Hirschenberger
committed
feat: updade configuration sketch
merged sketches for different can interfaces to one and make it configureable. Change MCP2515 library to adafruit library TODO: Test with hardware
1 parent cc14d66 commit 4f5da74

File tree

7 files changed

+428
-392
lines changed

7 files changed

+428
-392
lines changed

.github/workflows/ciWorkflows.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,9 @@ jobs:
5656
5757
- name: Install Arduino Libraries
5858
run: |
59-
arduino-cli lib install "autowp-mcp2515"
59+
arduino-cli lib install "Adafruit MCP2515"
6060
arduino-cli lib install "Adafruit CAN"
61+
arduino-cli lib install "Adafruit NeoPixel"
6162
# Add more libraries as needed
6263
6364
- name: Compile Keypad configuration example

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
</br>
1010
This library enables control of a PKP-3500-SI-MT CAN Keypad using any CAN bus interface with an Arduino-compatible microcontroller. This project is a fork of [PKP2600SI-Arduino-CAN-Controller](https://github.com/Mbmatthews/PKP2600SI-Arduino-CAN-Controller), created to extend support to the PKP-3500-SI-MT model. Due to inconsistencies in the interface and varying hardware requirements, the library has been rewritten to be hardware-independent with minimal dependencies.
1111

12+
## Caution
13+
This library is still under development - The arduino example sketches have not been thoroughly tested. Use at your own risk.
14+
1215
## Features
1316
- Hardware Independence: Works with any CAN hardware interface compatible with Arduino.
1417
- Message Processing: Processes messages from the PKP-3500-SI-MT and notifies if a message is not consumed.

examples/Pkp3500SiMt_AdafruitFeatherM4Can/Pkp3500SiMt_AdafruitFeatherM4Can.ino

+15-15
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
/* Brandon Matthews
2-
* Stefan Hirschenberger
3-
* Example for PKP-3500-SI-MT on Adafruit Feather M4 Can
1+
/**
2+
* @brief Example for PKP-3500-SI-MT on Adafruit Feather M4 Can
3+
* @author Brandon Matthews, Stefan Hirschenberger
44
*/
55

6-
#define KEYPAD_BASE_ID 0x15
6+
#define KEYPAD_BASE_ID 0x15
7+
#define CAN_BUS_BAUDRATE 125000
78

89
#include <Adafruit_NeoPixel.h>
910
#include <BlinkMarinePkpCanOpen.h>
@@ -12,14 +13,13 @@
1213
//Prototype for hardware specific callback function
1314
uint8_t transmittMessageCallBack(const struct can_frame& txMsg);
1415

15-
CANSAME5x CAN;
16+
CANSAME5x can;
1617
Pkp keypad(KEYPAD_BASE_ID, transmittMessageCallBack);
1718
Adafruit_NeoPixel pixel(1, 8, NEO_GRB + NEO_KHZ800);
1819

1920
void setup() {
2021

2122
pinMode(LED_BUILTIN, OUTPUT);
22-
2323
Serial.begin(115200);
2424
while (!Serial) {
2525
digitalWrite(LED_BUILTIN, (millis() % 500 > 250));
@@ -32,7 +32,7 @@ void setup() {
3232
Serial.println(F("PKP-3500-SI-MT Example Sketch started."));
3333

3434
// start the CAN bus at 250 kbps
35-
if (!CAN.begin(250000)) {
35+
if (!can.begin(CAN_BUS_BAUDRATE)) {
3636
Serial.println("Starting CAN failed!");
3737
while (1) {
3838
delay(10);
@@ -41,7 +41,7 @@ void setup() {
4141
Serial.println("Starting CAN!");
4242

4343
// register the receive callback
44-
CAN.onReceive(onReceive);
44+
can.onReceive(onReceive);
4545

4646
// Set Key color and blink states
4747
uint8_t colors1[4] = {Pkp::KEY_COLOR_BLANK, Pkp::KEY_COLOR_GREEN, Pkp::KEY_COLOR_BLANK, Pkp::KEY_COLOR_RED};
@@ -138,24 +138,24 @@ void loop() {
138138
}
139139

140140
uint8_t transmittMessageCallBack(const struct can_frame& txMsg) {
141-
CAN.beginPacket(txMsg.can_id, txMsg.can_dlc);
141+
can.beginPacket(txMsg.can_id, txMsg.can_dlc);
142142
for (int i = 0; i < txMsg.can_dlc; i++) {
143-
CAN.write(txMsg.data[i]);
143+
can.write(txMsg.data[i]);
144144
}
145-
CAN.endPacket();
145+
can.endPacket();
146146
return 0;
147147
}
148148

149149
void onReceive(int packetSize) {
150150
struct can_frame rxMsg;
151-
rxMsg.can_id = CAN.packetId();
152-
rxMsg.can_dlc = CAN.packetDlc();
151+
rxMsg.can_id = can.packetId();
152+
rxMsg.can_dlc = can.packetDlc();
153153
packetSize = min(packetSize, sizeof(rxMsg.data) / sizeof(rxMsg.data[0]));
154154
for (int i = 0; i < packetSize; i++) {
155-
if (CAN.peek() == -1) {
155+
if (can.peek() == -1) {
156156
break;
157157
}
158-
rxMsg.data[i] = (char)CAN.read();
158+
rxMsg.data[i] = (char)can.read();
159159
}
160160
keypad.process(rxMsg);
161161
}
Original file line numberDiff line numberDiff line change
@@ -1,122 +1,159 @@
1-
/* Brandon Matthews
2-
* Developed for Arduino UNO and MCP2515
3-
* Modified for PKP-3500-SI-MT
1+
/**
2+
* @brief Example for PKP-3500-SI-MT on Arduino with MCP2515
3+
* @author Brandon Matthews, Stefan Hirschenberger
44
*/
55

6-
// This library depends on and requires TimerOne library, SPI library, and autowp mcp2515 library v1.03
6+
#include <Adafruit_MCP2515.h>
77
#include <BlinkMarinePkpCanOpen.h>
8-
#include <mcp2515.h>
98

10-
#define CS_PIN 10
11-
#define INTERRUPT_PIN 3
12-
#define KEYPAD_BASE_ID 0x15
13-
#define ENABLE_PASSCODE false
9+
//Prototype for hardware specific callback function
10+
uint8_t transmittMessageCallBack(const struct can_frame& txMsg);
1411

15-
MCP2515 mcp2515(CS_PIN);
16-
PkpKeypad keypad(mcp2515, INTERRUPT_PIN, KEYPAD_BASE_ID, ENABLE_PASSCODE);
12+
#define KEYPAD_BASE_ID 0x15
13+
#define CAN_BUS_BAUDRATE 125000
14+
#define MCP_CS_PIN 10
15+
#define MCP_INT_PIN 3
16+
#define MCP_CLOCK_SPEED 8e6 //16e6 for 16MHz
1717

18-
unsigned long currentMillis;
19-
unsigned long key9OnTime = 0;
20-
bool lastKey9State;
18+
Adafruit_MCP2515 can(MCP_CS_PIN);
19+
Pkp keypad(KEYPAD_BASE_ID, transmittMessageCallBack);
2120

2221
void setup() {
22+
23+
pinMode(LED_BUILTIN, OUTPUT);
2324
Serial.begin(115200);
24-
keypad.setSerial(&Serial); // Required for the keypad library to print things out to serial
25+
while (!Serial) {
26+
digitalWrite(LED_BUILTIN, (millis() % 500 > 250));
27+
delay(10);
28+
if (millis() > 5000) {
29+
break;
30+
}
31+
}
32+
digitalWrite(LED_BUILTIN, LOW);
33+
Serial.println(F("PKP-3500-SI-MT Example Sketch started."));
34+
35+
// start the CAN bus at 250 kbps
36+
if (!can.begin(CAN_BUS_BAUDRATE)) {
37+
Serial.println("Starting CAN failed!");
38+
while (1) {
39+
delay(10);
40+
}
41+
}
42+
Serial.println("Starting CAN!");
2543

26-
uint8_t keypadPasscode[4] = {1, 2, 3, 4};
27-
keypad.setKeypadPassword(keypadPasscode);
28-
keypad.setKeyBrightness(70);
29-
keypad.setBacklight(BACKLIGHT_AMBER, 10);
44+
// register the receive callback
45+
can.onReceive(MCP_INT_PIN, onReceive);
3046

3147
// Set Key color and blink states
32-
uint8_t colors1[4] = {PKP_COLOR_BLANK, PKP_COLOR_YELLOW, PKP_COLOR_BLANK,
33-
PKP_COLOR_YELLOW}; // array for the 4 possible key states' respective colors
34-
uint8_t blinks1[4] = {PKP_COLOR_BLANK, PKP_COLOR_BLANK, PKP_COLOR_CYAN, PKP_COLOR_BLANK};
35-
36-
keypad.setKeyColor(PKP_KEY_2, colors1, blinks1);
37-
keypad.setKeyColor(PKP_KEY_3, colors1, blinks1);
38-
keypad.setKeyColor(PKP_KEY_4, colors1, blinks1);
39-
keypad.setKeyColor(PKP_KEY_5, colors1, blinks1);
40-
keypad.setKeyColor(PKP_KEY_6, colors1, blinks1);
41-
colors1[1] = PKP_COLOR_GREEN;
42-
keypad.setKeyColor(PKP_KEY_7, colors1, blinks1);
43-
keypad.setKeyColor(PKP_KEY_8, colors1, blinks1);
44-
keypad.setKeyColor(PKP_KEY_9, colors1, blinks1);
45-
keypad.setKeyColor(PKP_KEY_10, colors1, blinks1);
46-
colors1[1] = PKP_COLOR_RED;
47-
colors1[2] = PKP_COLOR_GREEN;
48-
colors1[3] = PKP_COLOR_BLUE;
49-
keypad.setKeyColor(PKP_KEY_12, colors1, blinks1);
50-
keypad.setKeyColor(PKP_KEY_13, colors1, blinks1);
51-
keypad.setKeyColor(PKP_KEY_14, colors1, blinks1);
52-
keypad.setKeyColor(PKP_KEY_15, colors1, blinks1);
53-
54-
keypad.setKeyMode(PKP_KEY_1, PkpKeypad::KEY_MODE_MOMENTARY);
55-
keypad.setKeyMode(PKP_KEY_2, PkpKeypad::KEY_MODE_MOMENTARY);
56-
keypad.setKeyMode(PKP_KEY_3, PkpKeypad::KEY_MODE_MOMENTARY);
57-
keypad.setKeyMode(PKP_KEY_4, PkpKeypad::KEY_MODE_MOMENTARY);
58-
keypad.setKeyMode(PKP_KEY_5, PkpKeypad::KEY_MODE_MOMENTARY);
59-
keypad.setKeyMode(PKP_KEY_6, PkpKeypad::KEY_MODE_MOMENTARY);
60-
keypad.setKeyMode(PKP_KEY_7, PkpKeypad::KEY_MODE_TOGGLE);
61-
keypad.setKeyMode(PKP_KEY_8, PkpKeypad::KEY_MODE_TOGGLE);
62-
keypad.setKeyMode(PKP_KEY_9, PkpKeypad::KEY_MODE_TOGGLE);
63-
keypad.setKeyMode(PKP_KEY_10, PkpKeypad::KEY_MODE_TOGGLE);
64-
keypad.setKeyMode(PKP_KEY_11, PkpKeypad::KEY_MODE_MOMENTARY);
65-
keypad.setKeyMode(PKP_KEY_12, PkpKeypad::KEY_MODE_CYCLE4);
66-
keypad.setKeyMode(PKP_KEY_13, PkpKeypad::KEY_MODE_TOGGLE);
67-
keypad.setKeyMode(PKP_KEY_14, PkpKeypad::KEY_MODE_TOGGLE);
68-
keypad.setKeyMode(PKP_KEY_15, PkpKeypad::KEY_MODE_CYCLE4);
69-
70-
71-
uint8_t defaultStates[PKP_MAX_KEY_AMOUNT] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
48+
uint8_t colors1[4] = {Pkp::KEY_COLOR_BLANK, Pkp::KEY_COLOR_GREEN, Pkp::KEY_COLOR_BLANK, Pkp::KEY_COLOR_RED};
49+
uint8_t blinks1[4] = {Pkp::KEY_COLOR_BLANK, Pkp::KEY_COLOR_BLANK, Pkp::KEY_COLOR_GREEN, Pkp::KEY_COLOR_BLANK};
50+
51+
keypad.setKeyColor(Pkp::KEY_2, colors1, blinks1);
52+
keypad.setKeyColor(Pkp::KEY_3, colors1, blinks1);
53+
keypad.setKeyColor(Pkp::KEY_4, colors1, blinks1);
54+
keypad.setKeyColor(Pkp::KEY_5, colors1, blinks1);
55+
keypad.setKeyColor(Pkp::KEY_6, colors1, blinks1);
56+
colors1[1] = Pkp::KEY_COLOR_GREEN;
57+
keypad.setKeyColor(Pkp::KEY_7, colors1, blinks1);
58+
keypad.setKeyColor(Pkp::KEY_8, colors1, blinks1);
59+
keypad.setKeyColor(Pkp::KEY_9, colors1, blinks1);
60+
keypad.setKeyColor(Pkp::KEY_10, colors1, blinks1);
61+
colors1[1] = Pkp::KEY_COLOR_RED;
62+
colors1[2] = Pkp::KEY_COLOR_GREEN;
63+
colors1[3] = Pkp::KEY_COLOR_BLUE;
64+
keypad.setKeyColor(Pkp::KEY_12, colors1, blinks1);
65+
keypad.setKeyColor(Pkp::KEY_13, colors1, blinks1);
66+
keypad.setKeyColor(Pkp::KEY_14, colors1, blinks1);
67+
keypad.setKeyColor(Pkp::KEY_15, colors1, blinks1);
68+
69+
keypad.setKeyMode(Pkp::KEY_1, Pkp::KEY_MODE_TOGGLE);
70+
keypad.setKeyMode(Pkp::KEY_2, Pkp::KEY_MODE_MOMENTARY);
71+
keypad.setKeyMode(Pkp::KEY_3, Pkp::KEY_MODE_MOMENTARY);
72+
keypad.setKeyMode(Pkp::KEY_4, Pkp::KEY_MODE_MOMENTARY);
73+
keypad.setKeyMode(Pkp::KEY_5, Pkp::KEY_MODE_MOMENTARY);
74+
keypad.setKeyMode(Pkp::KEY_6, Pkp::KEY_MODE_MOMENTARY);
75+
keypad.setKeyMode(Pkp::KEY_7, Pkp::KEY_MODE_TOGGLE);
76+
keypad.setKeyMode(Pkp::KEY_8, Pkp::KEY_MODE_TOGGLE);
77+
keypad.setKeyMode(Pkp::KEY_9, Pkp::KEY_MODE_TOGGLE);
78+
keypad.setKeyMode(Pkp::KEY_10, Pkp::KEY_MODE_TOGGLE);
79+
keypad.setKeyMode(Pkp::KEY_11, Pkp::KEY_MODE_MOMENTARY);
80+
keypad.setKeyMode(Pkp::KEY_12, Pkp::KEY_MODE_CYCLE4);
81+
keypad.setKeyMode(Pkp::KEY_13, Pkp::KEY_MODE_TOGGLE);
82+
keypad.setKeyMode(Pkp::KEY_14, Pkp::KEY_MODE_TOGGLE);
83+
keypad.setKeyMode(Pkp::KEY_15, Pkp::KEY_MODE_CYCLE4);
84+
85+
86+
int8_t defaultStates[PKP_MAX_KEY_AMOUNT] = {0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0};
7287
keypad.presetDefaultKeyStates(defaultStates);
73-
88+
keypad.applyDefaultKeyStates();
89+
keypad.setKeyBrightness(70);
90+
keypad.setBacklight(Pkp::BACKLIGHT_BLUE, 50);
7491
keypad.initializeEncoder(0, 16, 5);
7592
keypad.initializeEncoder(1, 16, 10);
7693

77-
keypad.begin(CAN_1000KBPS, MCP_8MHZ); // These are MCP settings to be passed
94+
keypad.begin();
7895
}
7996

80-
//----------------------------------------------------------------------------
81-
82-
uint8_t brightness = 0;
83-
uint32_t lastIncrement = 0;
84-
int16_t encoder = 0;
85-
8697
void loop() {
87-
currentMillis = millis();
8898

89-
keypad.process(); // must have this in main loop.
99+
static uint32_t key9OnTime = 0;
100+
static bool lastKey9State = 0;
101+
static uint32_t lastIncrement = 0;
102+
uint32_t currentMillis = millis();
90103

91-
if (keypad._keyState[PKP_KEY_1] == 1) {
104+
if (keypad.getKeyState(Pkp::KEY_1) == 1) {
92105
// do stuff
93106
}
94107

95-
// if key 9 is pressed, turn off after 2 seconds
96-
if (keypad._keyState[PKP_KEY_9] == 1 && lastKey9State == 0) {
108+
// if key 9 is release, blink for two seconds and turn off afterwards
109+
uint8_t key9State = keypad.getKeyState(Pkp::KEY_9);
110+
if (key9State == 0 && lastKey9State == 1) {
97111
key9OnTime = currentMillis;
112+
keypad.setKeyStateOverride(Pkp::KEY_9, 2);
98113
}
99-
lastKey9State = keypad._keyState[PKP_KEY_9];
100-
if (lastKey9State == 1 && (currentMillis - key9OnTime) > 2000) {
101-
keypad._keyState[PKP_KEY_9] = 0;
102-
keypad.update();
114+
if (key9OnTime + 2000 < currentMillis) {
115+
keypad.setKeyStateOverride(Pkp::KEY_9, -1);
103116
}
117+
lastKey9State = key9State;
104118

105-
int encoderOld = encoder;
106-
bool newData = false;
107-
uint16_t leds = 0;
108-
encoder += keypad.getRelativeEncoderTicks(0);
109-
encoder = constrain(encoder, 0, 16);
110119

111-
if (encoder != encoderOld) {
112-
for (int i = 0; i < encoder; i++) {
113-
leds |= 1 << i;
120+
bool newData = false;
121+
int32_t leds[2] = {-1, -1};
122+
for (int i = 0; i < 2; i++) {
123+
int16_t encoder = keypad.getEncoderPosition(i);
124+
for (int j = 0; j < encoder; j++) {
125+
leds[i] |= 1 << j;
114126
}
115-
newData = 1;
116127
}
128+
keypad.setEncoderLeds(leds);
129+
130+
if (keypad.getStatus() != Pkp::KPS_RX_WITHIN_LAST_SECOND) {
131+
digitalWrite(LED_BUILTIN, HIGH);
132+
delay(100);
133+
digitalWrite(LED_BUILTIN, LOW);
134+
delay(500);
135+
}
136+
}
137+
138+
uint8_t transmittMessageCallBack(const struct can_frame& txMsg) {
139+
can.beginPacket(txMsg.can_id, txMsg.can_dlc);
140+
for (int i = 0; i < txMsg.can_dlc; i++) {
141+
can.write(txMsg.data[i]);
142+
}
143+
can.endPacket();
144+
return 0;
145+
}
117146

118-
if (newData && lastIncrement + 50 < currentMillis) {
119-
keypad.setEncoderLed(0, leds);
120-
lastIncrement = currentMillis;
147+
void onReceive(int packetSize) {
148+
struct can_frame rxMsg;
149+
rxMsg.can_id = can.packetId();
150+
rxMsg.can_dlc = can.packetDlc();
151+
packetSize = min(packetSize, sizeof(rxMsg.data) / sizeof(rxMsg.data[0]));
152+
for (int i = 0; i < packetSize; i++) {
153+
if (can.peek() == -1) {
154+
break;
155+
}
156+
rxMsg.data[i] = (char)can.read();
121157
}
158+
keypad.process(rxMsg);
122159
}

0 commit comments

Comments
 (0)