master
Ondřej Hruška 9 years ago
parent 7665825ae1
commit e20cac2748
  1. 29
      README.md
  2. 147
      main.c

@ -1,11 +1,28 @@
# arduino-gamepad
super simple gamepad project where Pro Mini is in a gamepad and sends keys over USART
# Spatial RGB
LED connected to D9 (on-board one at D13).
## What
- Arduino
- 3 sonars
- 3 colors in the spectrum
- RGB led strip
- Magic!
## Building
To run this project, you need Arduino Pro Mini, or Nano (those $2 eBay clones will work perfectly).
You can also try to use a genuine Arduino, even larger (UNO), though I haven't tried that.
To flash the firmware, run `make flash`. Adjustment the Makefile as needed. Naturally, you'll need
`avr-gcc` and `avrdude` installed (and Linux or OSX).
Make sure the correct Serial device is defined in the Makefile (`/dev/ttyUSB0` or other - it tends
to be something really strange on OSX).
## Hardware
- RGB LED strip with WS2812 or WS2812B. It's set up for a 30-led strip, adjust as needed.
Buttons connected from pins to ground with internal pull-up.
Keys are sent as A - pressed, a - released (different letters), over UART at 115200 baud.
Key press is indicated by LED at D9.

147
main.c

@ -23,6 +23,53 @@
#define ECHO2_PIN 8
#define ECHO3_PIN 10
#define LED_COUNT 30
/** Phase of the measurement (state-machine state) */
typedef enum {
MEAS_WAIT_1,
MEAS_WAIT_0,
MEAS_DONE
} MeasPhase;
// averaging buffer length (number of samples)
#define MBUF_LEN 16
/** Averaging buffer instance */
typedef struct {
float data[MBUF_LEN];
} MBuf;
static MBuf mb_offs1;
static MBuf mb_offs2;
static MBuf mb_offs3;
/** RGB color structure */
typedef struct __attribute__((packed)) {
uint8_t r;
uint8_t g;
uint8_t b;
} RGB;
/** LED strip colors */
static RGB history[LED_COUNT];
/** Add a value to the averaging buffer. Returns currrent mean value */
static float mbuf_add(MBuf *buf, float value)
{
float aggr = value;
for (int i = MBUF_LEN - 1; i > 0; i--) {
float m = buf->data[i - 1];
aggr += m;
buf->data[i] = m;
}
buf->data[0] = value;
return aggr / (float)MBUF_LEN;
}
/** Wait long enough for the colors to show */
static inline __attribute__((always_inline))
@ -35,6 +82,9 @@ void ws_show(void)
static inline __attribute__((always_inline))
void ws_send_byte(uint8_t bb)
{
// If your LEDs don't work right, you may need to adjust the number of NOPs here
// It's a good idea to debug this with oscilloscope or a logic analyzer
for (int8_t i = 8; i > 0; i--) {
pin_up(WS_PIN);
if (bb & 0x80) {
@ -59,7 +109,7 @@ void ws_send_byte(uint8_t bb)
}
}
/** Send a RGB color to the strip */
static void ws_send_rgb(uint8_t r, uint8_t g, uint8_t b)
{
ws_send_byte(g);
@ -67,7 +117,7 @@ static void ws_send_rgb(uint8_t r, uint8_t g, uint8_t b)
ws_send_byte(b);
}
/** Init hardware resources */
static void hw_init(void)
{
usart_init(BAUD_115200);
@ -85,51 +135,18 @@ static void hw_init(void)
as_output(13);
}
typedef enum {
MEAS_WAIT_1,
MEAS_WAIT_0,
MEAS_DONE
} MeasPhase;
#define MBUF_LEN 16
typedef struct {
float data[MBUF_LEN];
} MBuf;
static float mbuf_add(MBuf *buf, float value)
{
float aggr = value;
for (int i = MBUF_LEN - 1; i > 0; i--) {
float m = buf->data[i - 1];
aggr += m;
buf->data[i] = m;
}
buf->data[0] = value;
return aggr / (float)MBUF_LEN;
}
static MBuf mb_offs1;
static MBuf mb_offs2;
static MBuf mb_offs3;
typedef struct {
uint8_t r;
uint8_t g;
uint8_t b;
} RGB;
static RGB history[30];
static uint16_t meas(MBuf *mbuf, uint8_t TRIG, uint8_t ECHO)
/**
* Measure one ultrasonic sensor distance
*
* We could run all 3 at once, but then the sound waves tend to reflect
* into different receives and you get false readings.
*/
static uint8_t meas(MBuf *mbuf, uint8_t trig_pin, uint8_t echo_pin)
{
_delay_ms(6);
pin_up_n(TRIG);
pin_up_n(trig_pin);
_delay_ms(1);
pin_down_n(TRIG);
pin_down_n(trig_pin);
MeasPhase meas_phase = MEAS_WAIT_1;
@ -140,12 +157,12 @@ static uint16_t meas(MBuf *mbuf, uint8_t TRIG, uint8_t ECHO)
while (true) {
if (meas_phase == MEAS_WAIT_1) {
if (pin_is_high_n(ECHO)) {
if (pin_is_high_n(echo_pin)) {
echo = TCNT1;
meas_phase = MEAS_WAIT_0;
}
} else if (meas_phase == MEAS_WAIT_0) {
if (pin_is_low_n(ECHO)) {
if (pin_is_low_n(echo_pin)) {
echo = TCNT1 - echo;
break;
}
@ -160,11 +177,13 @@ static uint16_t meas(MBuf *mbuf, uint8_t TRIG, uint8_t ECHO)
TCCR1B = 0; // stop
// Both pulses measured with 0.5us accuracy
// Pulse measured with 0.5us accuracy
// To convert to mm -> multiply by 0.8
// Convert to mm
// --- convert to R/G/B value 0-255 ---
float offset = 255 - echo / (1.25f * 25.0f); //25
// The number '25.0f' here determines the sensitivity
float offset = 255 - echo / (1.25f * 25.0f);
if (offset > 255) {
offset = 255;
@ -172,31 +191,31 @@ static uint16_t meas(MBuf *mbuf, uint8_t TRIG, uint8_t ECHO)
offset = 0;
}
// averaging
offset = mbuf_add(mbuf, offset);
return (uint16_t) roundf(offset); // converted to RGB-level
// to int
return (uint8_t) roundf(offset);
}
/** Measure all 3 sensors and update the colors */
static void sonar_measure(void)
{
uint16_t c1 = meas(&mb_offs1, TRIG1_PIN, ECHO1_PIN);
uint16_t c2 = meas(&mb_offs2, TRIG2_PIN, ECHO2_PIN);
uint16_t c3 = meas(&mb_offs3, TRIG3_PIN, ECHO3_PIN);
uint8_t c1 = meas(&mb_offs1, TRIG1_PIN, ECHO1_PIN);
uint8_t c2 = meas(&mb_offs2, TRIG2_PIN, ECHO2_PIN);
uint8_t c3 = meas(&mb_offs3, TRIG3_PIN, ECHO3_PIN);
for (int i = 30 - 1; i > 0; i--) {
for (int i = LED_COUNT - 1; i > 0; i--) {
history[i].r = history[i - 1].r;
history[i].g = history[i - 1].g;
history[i].b = history[i - 1].b;
}
history[0].r = (uint8_t)c1;
history[0].g = (uint8_t)c2;
history[0].b = (uint8_t)c3;
history[0].r = c1;
history[0].g = c2;
history[0].b = c3;
for (int i = 0; i < 30; i++) {
for (int i = 0; i < LED_COUNT; i++) {
ws_send_rgb(history[i].r, history[i].g, history[i].b);
}
@ -210,8 +229,8 @@ int main(void)
usart_puts_P(PSTR("===========================\r\n"));
usart_puts_P(PSTR("\r\n"));
usart_puts_P(PSTR("RGB SONAR DEMO\r\n"));
usart_puts_P(PSTR("FEL CVUT K338\r\n"));
usart_puts_P(PSTR("SPATIAL RGB - SONAR DEMO\r\n"));
usart_puts_P(PSTR("FEE CTU Prague, K338\r\n"));
usart_puts_P(PSTR("\r\n"));
usart_puts_P(PSTR("(c) Ondrej Hruska 2016\r\n"));
usart_puts_P(PSTR("\r\n"));
@ -230,7 +249,7 @@ int main(void)
if (++cnt == 20) {
cnt = 0;
pin_toggle(13);
pin_toggle(13); // blink the indicator to show that we're OK
}
}
}

Loading…
Cancel
Save