I'm just getting started with it, in my tiny shards of free time. Your code is in C (and a smattering of C++). I've hooked up four LEDs and two buttons that allow me to cycle the LEDs forward or backward. Since you're working at such a low level, you have to be aware of tiny factors such as key bounce (closing a switch will, for a short period, yield unstable results due to physical and electrical factors).
There's a tool called Fritzing to help you document your projects. It's very alpha, but the simple results are rather nice:
The code is still evolving:
#define FIRST_LED 12 #define LED_COUNT 4 #define DEBOUNCE_PERIOD 50 // ms class Debounce { public: Debounce(int pin); boolean read(); private: int _pin; int _previousValue; int _lastButtonDebounce; boolean _enabled; }; Debounce::Debounce(int pin) { _pin = pin; _previousValue = LOW; _lastButtonDebounce = 0; // never _enabled = true; pinMode(_pin, INPUT); } boolean Debounce::read() { int currentValue = digitalRead(_pin); long now = millis(); if (currentValue != _previousValue) { _lastButtonDebounce = now; _previousValue = currentValue; return false; } if (now - _lastButtonDebounce < DEBOUNCE_PERIOD) { return false; } // It's gone HIGH to LOW if (currentValue == LOW) { _enabled = true; return false; } // It's gone LOW to HIGH if (_enabled) { _enabled = false; return true; } return false; } // First press will move to the first LED. int currentLed = -1; Debounce advanceButton = Debounce(2); Debounce retreatButton = Debounce(3); void setup() { for (int i = 0; i < LED_COUNT; i++) { int pin = FIRST_LED - i; pinMode(pin, OUTPUT); digitalWrite(pin, HIGH); } delay(250); for (int i = 0; i < LED_COUNT; i++) { digitalWrite(FIRST_LED - i, LOW); } } void advance() { if (currentLed >= 0) digitalWrite(FIRST_LED - currentLed, LOW); if (++currentLed == LED_COUNT) currentLed = 0; digitalWrite(FIRST_LED - currentLed, HIGH); } void retreat() { if (currentLed >= 0) digitalWrite(FIRST_LED - currentLed, LOW); if (--currentLed < 0) currentLed = LED_COUNT - 1; digitalWrite(FIRST_LED - currentLed, HIGH); } void loop() { if (advanceButton.read()) advance(); if (retreatButton.read()) retreat(); }
Fun stuff ... and I don't see me writing a web framework for it, which is a change of pace.
My ultimate goal is to write Arduino apps in a Clojure DSL, and have Clojure generate the machine code for the AVR processor that runs the Arduino. Of course, that means learning AVR machine code and writing a lot of code to compile and assemble the DSL into something that can execute inside the Arduino.
Plan B: Perhaps its time to learn Forth?
you might miss this to fix the chaos with your buttons : http://en.wikipedia.org/wiki/Schmitt_trigger
ReplyDeleteBR and thanks for your nice tapestry framework!
YouTube it! Let's see it in action!
ReplyDeleteYou don't need to go to AVR machine code, it may be easier to generate the stylized C++ that the Arduino IDE uses, and use its facilities to compile and load that onto the board. I'd suggest at first allowing limited Clojure constructs in your DSL (e.g. simple closure-based iteration, conditionals, etc.) and require Clojure type annotations.
ReplyDeleteThere's a comparable Ruby project for this rad.rubyforge.org but of course Ruby lacks macros & type annotations so it does not work that great.
Would love to know if you actually get going with this!