A somewhat silly project that uses an LPC11U24 to control the system, a Neopixel stick to provide light, and a sound FX board with a small speaker to make noise. I set the pins to inputs with pull-ups then connected 14 jumper wires to ground. Every time a wire was disconnected, the system changed its lighting pattern: color, blink timing, blink pattern (blink to white, black, random, or opposite the main color). The system also played a random audio clip. More details on http://embedded.fm/blog/2016/5/24/fistful-of-wires License: CC-A-NC
Diff: main.cpp
- Revision:
- 0:21fea82c85fc
- Child:
- 1:0a051df78be2
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sun May 15 18:06:06 2016 +0000 @@ -0,0 +1,268 @@ +/* + Fist full of wires! + The intention here is to make a ball of wires that someone can reach in and + grab, changing the behavior of the system. + + So we read in the free IO lines, build up a variable. + If it has changed, + do the change actions: + make a bzzzzt sound + vibrate the motor + turn off all of the LEDs for a brief instant + + Use the created variable to choose the neopixel pattern + and the sound pattern to output to the audio (intermittent beeps) + + + This program depends on neopixel library. + http://developer.mbed.org/users/JacobBramley/code/PixelArray/ + + Audio (R2D2 sounds) from Szilard Liptak: + https://developer.mbed.org/users/Szilard/notebook/mbed-r2d2-robot/ + Sounds in general: https://developer.mbed.org/users/4180_1/notebook/using-a-speaker-for-audio-output/ + + Todo: + Blinking needs a timer attachment + + + +*/ +#include "mbed.h" +#include "neopixel.h" +#include "SongPlayer.h" + + #include <stdlib.h> /* srand, rand */ +#define NLED (8) +#define ONE_COLOR + +BusIn mColorWires( + p20, p19, p18, p17, p16, p15 // six color, two each, RGB + ); +BusIn mBlinkConfig( + p14, p13, p12, // three timing: indexes into mBlinkTiming + p30, p29 ); // two for blink type + +typedef union { + struct + { + uint32_t green:2; + uint32_t blue:2; + uint32_t red:2; + uint32_t junk:26; + }; + uint32_t value; +} tLedBehaviorWires; + +BusIn mLedBitmask (p11, p10, p9, p8, p36, p35, p34, p33); // eight to for bitmask which LED indexes are on... this is not enough of a difference + +#define COLOR_WHITE 0xFFFFFF +#define COLOR_BLACK 0x000000 + +void InitializePins(void); +void AllOneColorLeds(neopixel::Pixel * out, uint32_t index, uintptr_t color); +void OnChangeMode(neopixel::PixelArray array); +neopixel::Pixel GetCurrentColor(uint32_t wireConfig); +void SetLeds(neopixel::Pixel * out, uint32_t index, uintptr_t wireConfig); + +class LedArrayController { +public: + LedArrayController(BusIn *bus, neopixel::PixelArray *array) : mBus(bus), mArray(array) + { + mBus->mode(PullUp); + srand (time(NULL)); + } + void OnChangeMode(uint32_t baseColor) + { + // 000 001 010 011 100 101 110, 111 + const float mBlinkTiming[] = {1.0, 0.1, 0.5, 0.0, 2.0, 0.0, 0.0, 5.0}; + mBaseColor = baseColor; + mIsBaseColor = false; + mBehavior.value = *mBus; + Update(); + + mTiming = mBlinkTiming[mBehavior.timingIndex]; + if (mTiming > 0.0f) + { + mTimer.attach(this, &LedArrayController::Update, mTiming); + } else { + mTimer.detach(); + } + } + void Update() { + // called by timer for updating LEDs: + if (mIsBaseColor) + { + switch (mBehavior.type) { + case (BLINK_TO_WHITE): + mArray->update(AllOneColorLeds, NLED, COLOR_WHITE); + break; + case (BLINK_TO_BLACK): + mArray->update(AllOneColorLeds, NLED, COLOR_BLACK); + break; + case (BLINK_TO_RANDOM): + mArray->update(AllOneColorLeds, NLED, (rand() & COLOR_WHITE)); + break; + case (BLINK_TO_OPPOSITE): + mArray->update(AllOneColorLeds, NLED, ~mBaseColor); + break; + } + mIsBaseColor = false; + + } else { + // set to base color + mArray->update(AllOneColorLeds, NLED, mBaseColor); + mIsBaseColor = true; + } + mTimer.attach(this, &LedArrayController::Update, mTiming); + + } +private: + float mTiming; + BusIn *mBus; + neopixel::PixelArray *mArray; + Timeout mTimer; + bool mIsBaseColor; + uint32_t mBaseColor; + typedef enum {BLINK_TO_WHITE=0, BLINK_TO_BLACK=1, BLINK_TO_RANDOM=2, BLINK_TO_OPPOSITE=3 } eBlinkType; + union { + struct { + uint32_t timingIndex:3; + uint32_t type:2; + uint32_t junk:28; + }; + uint32_t value; + } mBehavior; +}; + + +void InitializePins(void) +{ + mColorWires.mode(PullUp); + mLedBitmask.mode(PullUp); + mBlinkConfig.mode(PullUp); +} + +void OnChangeMode(neopixel::PixelArray array) +{ + // FIXME play bzzzt sound + + // all white, delay all black + array.update(AllOneColorLeds, NLED, COLOR_WHITE); + wait_ms(200); + array.update(AllOneColorLeds, NLED, COLOR_BLACK); + wait_ms(200); + // FIXME mBlinkTimer.detach(); // clear timer functionality +} + +uint8_t MakeColorFromWires(uint32_t singleColorWireConfig) +{ + uint8_t color; + if (singleColorWireConfig == 3u) { color = 0xFF; } + else if (singleColorWireConfig == 0u) { color = 0x00; } + else /* one bit on */ { color = 0x80; } + return color; +} + +void AllOneColorLeds(neopixel::Pixel * out, uint32_t index, uintptr_t color) +{ + out->red = (color >> 16) & 0xFF; + out->green = (color >> 8 ) & 0xFF; + out->blue = (color ) & 0xFF; +} + +uint32_t GetCurrentColorU32(uint32_t wireConfig) +{ + neopixel::Pixel pix; + uint32_t out; + pix = GetCurrentColor(wireConfig); + out = pix.blue + (pix.green << 8) + (pix.red << 16); + return out; +} + + +neopixel::Pixel GetCurrentColor(uint32_t wireConfig) +{ + tLedBehaviorWires config; + neopixel::Pixel out; + config.value = wireConfig; + if ( (config.red == 0u) && (config.green == 0u) && (config.blue == 0u) ) + { + out.red = 0x10u; + out.green = 0x10u; + out.blue = 0x10u; + } else { + out.red = MakeColorFromWires(config.red); + out.green = MakeColorFromWires(config.green); + out.blue = MakeColorFromWires(config.blue); + } + return out; +} +void SetLeds(neopixel::Pixel * out, uint32_t index, uintptr_t wireConfig) + { + bool thisOneOn = false; + uint32_t indexMask = 1u << index; + + indexMask &= mLedBitmask; + if (indexMask) // if this one set + { + thisOneOn = true; + } else if (mLedBitmask == 0u) // all wires plugged in, let all LEDs turn on + { + thisOneOn = true; + } + + if (thisOneOn) + { + *out = GetCurrentColor(wireConfig); + } else { + AllOneColorLeds(out, index, COLOR_BLACK); + } + } + + +int main() { + uint32_t ledBehaviorWires; + uint32_t ledBitMask; + uint32_t ledBlinkConfig; + bool change = true; + neopixel::PixelArray array(p5); + LedArrayController ledArrayController(&mBlinkConfig, &array); + // SongPlayer mySpeaker(p21); + + InitializePins(); + +// float note[18]= {3520, 3135.96, 2637.02, 2093, 2349.32, 3951.07, 2793.83, 4186.01, 3520, 3135.96, 2637.02, 2093, 2349.32, 3951.07, 2793.83, 4186.01}; //R2D2 sound effect +// float duration[18]= {0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1}; //for a bit of variety, multiple sound samples could be chosen at random + +// float note[18]= {1568.0,1396.9,1244.5,1244.5,1396.9,1568.0,1568.0,1568.0,1396.9, +// 1244.5,1396.9,1568.0,1396.9,1244.5,1174.7,1244.5,1244.5, 0.0 +// }; +//float duration[18]= {0.48,0.24,0.72,0.48,0.24,0.48,0.24,0.24,0.24, + // 0.24,0.24,0.24,0.24,0.48,0.24,0.48,0.48, 0.0 + // }; + +// uint32_t val = 0; + while (1) + { + if ((ledBehaviorWires != mColorWires) || + (ledBitMask != mLedBitmask) || + (ledBlinkConfig != mBlinkConfig) ) + { + change = true; + } + if (change) + { + change = false; + ledBehaviorWires = mColorWires; + ledBitMask = mLedBitmask; + ledBlinkConfig = mBlinkConfig; + ledArrayController.OnChangeMode(GetCurrentColorU32(ledBehaviorWires)); +// OnChangeMode(array); + + array.update(SetLeds, NLED, ledBehaviorWires); + } + +// mySpeaker.PlaySong(note,duration); //play R2D2 sound effects + wait_ms(10); + } +} \ No newline at end of file