Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

arduino for buttons #87

Merged
merged 4 commits into from
Mar 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
What's here:

* **comp**: RoboRIO competition code for 2025
* **console**: Button board hardware and code
* **doc**: Documentation: look here for instructions!
* **lib**: Evergreen RoboRIO library code
* **raspberry_pi** Coprocessor tasks: vision, logging, GTSAM
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
5 changes: 5 additions & 0 deletions console/arduino/buttons_2025/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Buttons 2025

The 2025 button board consists of 32 discrete switches, wired
to two Adafruit MCP23017 I/O boards, which are connected to
a Sparkfun Arduino Pro Micro via I2C.
99 changes: 99 additions & 0 deletions console/arduino/buttons_2025/Sensor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#ifndef SENSOR_H
#define SENSOR_H
#include "Data.h"
#include <Adafruit_MCP23X17.h>

/**
* The sensor consists of two MCP23017 boards.
*/
class Sensor {
public:
/**
* Sets pin modes.
*/
void initialize() {
mcp0.begin_I2C(0x20);
mcp1.begin_I2C(0x21);
// These are the "A" pins.
mcp0.pinMode(0, INPUT_PULLUP);
mcp0.pinMode(1, INPUT_PULLUP);
mcp0.pinMode(2, INPUT_PULLUP);
mcp0.pinMode(3, INPUT_PULLUP);
mcp0.pinMode(4, INPUT_PULLUP);
mcp0.pinMode(5, INPUT_PULLUP);
mcp0.pinMode(6, INPUT_PULLUP);
mcp0.pinMode(7, INPUT_PULLUP);
// These are the "B" pins.
mcp0.pinMode(8, INPUT_PULLUP);
mcp0.pinMode(9, INPUT_PULLUP);
mcp0.pinMode(10, INPUT_PULLUP);
mcp0.pinMode(11, INPUT_PULLUP);
mcp0.pinMode(12, INPUT_PULLUP);
mcp0.pinMode(13, INPUT_PULLUP);
mcp0.pinMode(14, INPUT_PULLUP);
mcp0.pinMode(15, INPUT_PULLUP);
// These are the "A" pins.
mcp1.pinMode(0, INPUT_PULLUP);
mcp1.pinMode(1, INPUT_PULLUP);
mcp1.pinMode(2, INPUT_PULLUP);
mcp1.pinMode(3, INPUT_PULLUP);
mcp1.pinMode(4, INPUT_PULLUP);
mcp1.pinMode(5, INPUT_PULLUP);
mcp1.pinMode(6, INPUT_PULLUP);
mcp1.pinMode(7, INPUT_PULLUP);
// These are the "B" pins.
mcp1.pinMode(8, INPUT_PULLUP);
mcp1.pinMode(9, INPUT_PULLUP);
mcp1.pinMode(10, INPUT_PULLUP);
mcp1.pinMode(11, INPUT_PULLUP);
mcp1.pinMode(12, INPUT_PULLUP);
mcp1.pinMode(13, INPUT_PULLUP);
mcp1.pinMode(14, INPUT_PULLUP);
mcp1.pinMode(15, INPUT_PULLUP);
}

/**
* Reads the switch state and writes the values into reportTx.
*/
void sense(ReportTx& reportTx) {
uint16_t gpio0 = mcp0.readGPIOAB();
uint16_t gpio1 = mcp1.readGPIOAB();
reportTx.b1 = gpio0 & 0b0000000000000001;
reportTx.b2 = gpio0 & 0b0000000000000010;
reportTx.b3 = gpio0 & 0b0000000000000100;
reportTx.b4 = gpio0 & 0b0000000000001000;
reportTx.b5 = gpio0 & 0b0000000000010000;
reportTx.b6 = gpio0 & 0b0000000000100000;
reportTx.b7 = gpio0 & 0b0000000001000000;
reportTx.b8 = gpio0 & 0b0000000010000000;
reportTx.b9 = gpio0 & 0b0000000100000000;
reportTx.b10 = gpio0 & 0b0000001000000000;
reportTx.b11 = gpio0 & 0b0000010000000000;
reportTx.b12 = gpio0 & 0b0000100000000000;
reportTx.b13 = gpio0 & 0b0001000000000000;
reportTx.b14 = gpio0 & 0b0010000000000000;
reportTx.b15 = gpio0 & 0b0100000000000000;
reportTx.b16 = gpio0 & 0b1000000000000000;
reportTx.b17 = gpio1 & 0b0000000000000001;
reportTx.b18 = gpio1 & 0b0000000000000010;
reportTx.b19 = gpio1 & 0b0000000000000100;
reportTx.b20 = gpio1 & 0b0000000000001000;
reportTx.b21 = gpio1 & 0b0000000000010000;
reportTx.b22 = gpio1 & 0b0000000000100000;
reportTx.b23 = gpio1 & 0b0000000001000000;
reportTx.b24 = gpio1 & 0b0000000010000000;
reportTx.b25 = gpio1 & 0b0000000100000000;
reportTx.b26 = gpio1 & 0b0000001000000000;
reportTx.b27 = gpio1 & 0b0000010000000000;
reportTx.b28 = gpio1 & 0b0000100000000000;
reportTx.b29 = gpio1 & 0b0001000000000000;
reportTx.b30 = gpio1 & 0b0010000000000000;
reportTx.b31 = gpio1 & 0b0100000000000000;
reportTx.b32 = gpio1 & 0b1000000000000000;
}

private:
Adafruit_MCP23X17 mcp0;
Adafruit_MCP23X17 mcp1;
};
#endif // SENSOR_H
21 changes: 21 additions & 0 deletions console/arduino/buttons_2025/buttons_2025.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include "Data.h"
#include "Transceiver.h"
#include "Sensor.h"

ReportRx reportRx_;
ReportTx reportTx_;
Sensor sensor_;
Transceiver transceiver_(Transceiver::SubConsole::BUTTONS_2025, reportRx_);

void setup() {
sensor_.initialize();
}

void loop() {
sensor_.sense(reportTx_);
transceiver_.send(reportTx_);
// The sensor has an issue triggered by state changes during I2C transmission:
// https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library/issues/96
// To minimize the incidence of that bug, minimize the sample rate.
delay(100);
}
File renamed without changes.
File renamed without changes.
4 changes: 4 additions & 0 deletions console/arduino/key_array/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Key Array

The key array uses keyboard switches and a keyboard-style
PCB connected as a crosspoint switch array.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Adafruit MCP23017 Arduino Library [![Build Status](https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library/actions)[![Documentation](https://github.com/adafruit/ci-arduino/blob/master/assets/doxygen_badge.svg)](http://adafruit.github.io/Adafruit-MCP23017-Arduino-Library/html/index.html)

This is a library for the MCP23008/17 I2C and MCP23S08/17 SPI Port Expanders.

Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!

Written by Carter Nelson for Adafruit Industries.
BSD license, check license.txt for more information
All text above must be included in any redistribution

To install, use the Arduino IDE Library Manager.

# Pin Addressing

When using single pin operations such as _pinMode(pinId, dir)_ or _digitalRead(pinId)_ or _digitalWrite(pinId, val)_ then the pins are addressed using the ID's below. For example, for set the mode of _GPB0_ then use _pinMode(8, ...)_. **NOTE** The MCP23008 and MCP23S08 only have _GPAx_ pins.

| MCP23x08 Pin # | MCP23x17 Pin # | Pin Name | Pin ID |
| :------------: | :------------: | :------: | :----: |
| 10 | 21 | GPA0 | 0 |
| 11 | 22 | GPA1 | 1 |
| 12 | 23 | GPA2 | 2 |
| 13 | 24 | GPA3 | 3 |
| 14 | 25 | GPA4 | 4 |
| 15 | 26 | GPA5 | 5 |
| 16 | 27 | GPA6 | 6 |
| 17 | 28 | GPA7 | 7 |
| -- | 1 | GPB0 | 8 |
| -- | 2 | GPB1 | 9 |
| -- | 3 | GPB2 | 10 |
| -- | 4 | GPB3 | 11 |
| -- | 5 | GPB4 | 12 |
| -- | 6 | GPB5 | 13 |
| -- | 7 | GPB6 | 14 |
| -- | 8 | GPB7 | 15 |

# Use of HW address pins for SPI device

Library supports MCP23Sxx HW pin addressing (A2, A1, A0 for S17 and A1, A0 for S08)
To use it provide HW address to begin_SPI(CS, SPI, HW_ADDR) function, and as a result each SPI message will contain correct chip address.

Example:
mcp.begin_SPI(10, &SPI, 0b101);

HW Address recognition must be enabled by enableAddrPins() function. **NOTE** Calling enableAddrPins() will enable IOCON.HAEN bit for all active (CS low) devices on SPI bus.
**NOTE**
There is hardware bug in the MCP23S17 chip, see "MCP23S17 Rev. A Silicon Errata".
As a result, if using device with A2 = high, and not using addressing, hw address must be set to 0b1XX
In such case, even if not using addressing, initalize your MCP23S17 chip with 0b1XX address, eg: mcp.begin_SPI(10, &SPI, 0b100);.

# Warning

Some people have reported an undocumented bug that can potentially corrupt the I2C bus.
It occurs if an MCP230XX input pin state changes during I2C readout. **This should be very rare.** For more information, see this [forum post](https://www.microchip.com/forums/m646539.aspx) and this [knowledge base article](https://microchipsupport.force.com/s/article/On-MCP23008-MCP23017-SDA-line-change-when-GPIO7-input-change>).
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Blinks an LED attached to a MCP23XXX pin.

// ok to include only the one needed
// both included here to make things simple for example
#include <Adafruit_MCP23X08.h>
#include <Adafruit_MCP23X17.h>

#define LED_PIN 0 // MCP23XXX pin LED is attached to

// only used for SPI
#define CS_PIN 6

// uncomment appropriate line
Adafruit_MCP23X08 mcp;
//Adafruit_MCP23X17 mcp;

void setup() {
Serial.begin(9600);
//while (!Serial);
Serial.println("MCP23xxx Blink Test!");

// uncomment appropriate mcp.begin
if (!mcp.begin_I2C()) {
//if (!mcp.begin_SPI(CS_PIN)) {
Serial.println("Error.");
while (1);
}

// configure pin for output
mcp.pinMode(LED_PIN, OUTPUT);

Serial.println("Looping...");
}

void loop() {
mcp.digitalWrite(LED_PIN, HIGH);
delay(500);
mcp.digitalWrite(LED_PIN, LOW);
delay(500);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Reads a button attached to a MCP23XXX pin.

// ok to include only the one needed
// both included here to make things simple for example
#include <Adafruit_MCP23X08.h>
#include <Adafruit_MCP23X17.h>

#define BUTTON_PIN 1 // MCP23XXX pin button is attached to

// only used for SPI
#define CS_PIN 6

// uncomment appropriate line
Adafruit_MCP23X08 mcp;
//Adafruit_MCP23X17 mcp;

void setup() {
Serial.begin(9600);
//while (!Serial);
Serial.println("MCP23xxx Button Test!");

// uncomment appropriate mcp.begin
if (!mcp.begin_I2C()) {
//if (!mcp.begin_SPI(CS_PIN)) {
Serial.println("Error.");
while (1);
}

// configure pin for input with pull up
mcp.pinMode(BUTTON_PIN, INPUT_PULLUP);

Serial.println("Looping...");
}

void loop() {
// LOW = pressed, HIGH = not pressed
if (!mcp.digitalRead(BUTTON_PIN)) {
Serial.println("Button Pressed!");
delay(250);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Controls an LED via an attached button.

// ok to include only the one needed
// both included here to make things simple for example
#include <Adafruit_MCP23X08.h>
#include <Adafruit_MCP23X17.h>

#define LED_PIN 0 // MCP23XXX pin LED is attached to
#define BUTTON_PIN 1 // MCP23XXX pin button is attached to

// only used for SPI
#define CS_PIN 6

// uncomment appropriate line
Adafruit_MCP23X08 mcp;
//Adafruit_MCP23X17 mcp;

void setup() {
Serial.begin(9600);
//while (!Serial);
Serial.println("MCP23xxx Combo Test!");

// uncomment appropriate mcp.begin
if (!mcp.begin_I2C()) {
//if (!mcp.begin_SPI(CS_PIN)) {
Serial.println("Error.");
while (1);
}

// configure LED pin for output
mcp.pinMode(LED_PIN, OUTPUT);

// configure button pin for input with pull up
mcp.pinMode(BUTTON_PIN, INPUT_PULLUP);

Serial.println("Looping...");
}

void loop() {
mcp.digitalWrite(LED_PIN, !mcp.digitalRead(BUTTON_PIN));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// NOTE: This is a simple example that only reads the INTA or INTB pin
// state. No actual interrupts are used on the host microcontroller.
// MCP23XXX supports the following interrupt modes:
// * CHANGE - interrupt occurs if pin changes to opposite state
// * LOW - interrupt occurs while pin state is LOW
// * HIGH - interrupt occurs while pin state is HIGH

// ok to include only the one needed
// both included here to make things simple for example
#include <Adafruit_MCP23X08.h>
#include <Adafruit_MCP23X17.h>

#define BUTTON_PIN 1 // MCP23XXX pin used for interrupt

#define INT_PIN 7 // microcontroller pin attached to INTA/B

// only used for SPI
#define CS_PIN 6

// uncomment appropriate line
Adafruit_MCP23X08 mcp;
//Adafruit_MCP23X17 mcp;

void setup() {
Serial.begin(9600);
//while (!Serial);
Serial.println("MCP23xxx Interrupt Test!");

// uncomment appropriate mcp.begin
if (!mcp.begin_I2C()) {
//if (!mcp.begin_SPI(CS_PIN)) {
Serial.println("Error.");
while (1);
}

// configure MCU pin that will read INTA/B state
pinMode(INT_PIN, INPUT);

// OPTIONAL - call this to override defaults
// mirror INTA/B so only one wire required
// active drive so INTA/B will not be floating
// INTA/B will be signaled with a LOW
mcp.setupInterrupts(true, false, LOW);

// configure button pin for input with pull up
mcp.pinMode(BUTTON_PIN, INPUT_PULLUP);

// enable interrupt on button_pin
mcp.setupInterruptPin(BUTTON_PIN, LOW);

Serial.println("Looping...");
}

void loop() {
if (!digitalRead(INT_PIN)) {
Serial.print("Interrupt detected on pin: ");
Serial.println(mcp.getLastInterruptPin());
Serial.print("Pin states at time of interrupt: 0b");
Serial.println(mcp.getCapturedInterrupt(), 2);
delay(250); // debounce
// NOTE: If using DEFVAL, INT clears only if interrupt
// condition does not exist.
// See Fig 1-7 in datasheet.
mcp.clearInterrupts(); // clear
}
}
Loading