Since I had the usual stack of leftover PCBs from Seeed, I decided to buy up the parts for the rest of the boards and offer it as a kit on Tindie. It's a (mostly) Arduino-compatible ATmega328 board with clock & sensors that drives a charlieplexed 10x11 grid of 5mm LEDs. It's pretty easy to put together, and the default firmware plays Conway's Life between displaying the time & temperature. The graphics library is fairly complete with support for 7 brightnesses per pixel and the usual line/box/circle drawing routines, although for the most part the basic display is currently just banging pixels to the display directly. There's a font handler than can scroll text across the display, as well.
Comms are handled through an FTDI header while power is provided over USB or the FTDI connector.
Why go through all that trouble? Just use the latest version of WinAVR and be done with it.
Wrong OS. I've been tempted to see about switching to avr-gcc and a more traditional make / compile / link process, though. But that feels like a bit more trouble anyway. I'm not entirely sure what I'd be leaving behind and what I'd be gaining in the process. Just not sure I'm ready to leave the nest, as it were.
Although that said, if there's a project and target I would convert with, this is probably it. Limited dependencies by nature and a light touch on the Arduino-isms, hrm. Might be an alternative option.
I do, but mostly only for my own code. I could probably dig into the dropbox changelog if anything particular comes up, though. That said, I probably overspoke - thinking back on it I probably only extended the boards.txt file for additional BOD levels and clocks, and I made up a separate bundle of the Arduino environment with the updated toolchain to get past the PCREL linker error. Part of my goal this week is to try to get my local Arduino toolchain back to as close to the distribution defaults as possible again, then re-apply changes in a controlled and documented manner so I know what I've all changed.
So I've been ripping out my hair for the past week or so trying to debug an issue I've been having with a little tiny85 blinkenlichten I've been working on where a switch that falls through to a sleep after timing out worked for 8 modes out of 9, but the 9th mode just never slept consistently, the sketch seemed like it was restarting from loop() whenever I break'ed out of the function the switch case called. But only that particular function, and only part of the time and and and. Maddening, especially when it seemed to exhibit itself more when I let it run longer.
I finally just decided to go all in and switch over to the arduino-tiny core instead of the HLT core and after tweaking speeds (it's all nests of delay loops, so compiler optimizations affect it), initial results are promising. It sleeps when it should be! Power draw is what I expect - actually less in the main loop, by a third, and it still enters the low power sleep like I want it to. The arduino-tiny core includes the 16MHz PLL clock on the tiny85 without having to muck around in boards.txt, too!
It was far less annoying to switch than I had been afraid it would be after all the personalizations I'd made to the HLT core that I wasn't sure I'd remember. My code just up and compiled, although not with the appbundle I have for the Arduino Tiny with the PCREL-proof upgraded avr-gcc toolchain. Eh, Tom Carpenter's replacement ld should solve the 4k barrier when I start hitting it again.
(...of course, I'm sure I've jinxed it by suggesting that it seems to be working now...)
avrdude: Device signature = 0x1e950f avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed To disable this feature, specify the -D option. avrdude: erasing chip avrdude: warning: cannot set sck period. please check for usbasp firmware update. avrdude: reading input file "lfuse-LifeClock.hex" avrdude: writing lfuse (1 bytes):
avrdude: verifying ... avrdude: verification error, first mismatch at byte 0x0000 0xde != 0xd9 avrdude: verification error; content mismatch
avrdude: safemode: hfuse changed! Was de, and is now d9 Would you like this fuse to be changed back? [y/n]
Clearly, hfuse is failing to write and verify the first time. But I would swear that it works flawlessly every time (on that chip) after that. Am I missing some intricacy of avrdude and fuses - i.e. lfuse in one run, hfuse in another run, then go ahead and do flash and eeprom in a combined run?
If I were to use a bootloader, there would be a boot wait while waiting for a signal on the serial port.. without a bootloader, it runs immediately without any of that delay- another consideration.
Well, that isn't entirely true - I've been using a variant of optiboot that only pauses after a reset, on cold boot it starts immediately. It's weird going back to my stock Arduino and re-discovering the cold boot delay. But it is nice flashing my in-circuit ATtiny85 projects just by hitting the upload button and having it start immediately after flashing.
Now that the ATMEGA prices are reaching such low points, I'll be building all sorts of nonsense.. and not bothering to make reusable shields when the headers are more expensive than just committing a whole MCU to a build..
You're telling me - I was recently tempted by an auction of ATmega8's on eBay that was on the close order of a buck a chip delivered. That's cheaper than I'm getting ATtiny85's! More GPIO, same flash and memory, same basic level of avr-gcc support, the only thing that stopped me was my overflowing bin of parts I've accumulated.
long __attribute__ ((section (".noinit"))) resetCount;
The tricky bit now is to have it initialized the first time. Something like this: (...snip...)
Ah yeah, I tried simplifying the .noinit from the tinycylon code to be a straightforward variable, but I must have missed it by a hair, because when I tried it it ended up generating Java errors, not even avr-gcc errors. I know emacs' gcc mode was puzzled by it, but in my 2 hours past bedtime fog I didn't commit it so I couldn't even say how I screwed it up.
I had been using eeprom previously, and I might go back to it. But while previously I had been writing after every reset, now I can use resets as a mode selector until it times out, then it writes the selected mode to eeprom. Even though the various flash destroyers have convinced me that Atmel's 100,000 write claim is highly pessimistic, I may as well limit how often I'm beating it up - there's always crib death.
And I see the difference between monitoring for a cold boot via PORF versus checking for uninitialized garbage. Belt and suspenders. I'll see about implementing that after work.
Thanks again, though - that was the nudge in the right direction!
(light_led just lights the appropriate LED, in lieu of getting SoftwareSerial running)
In practice, on cold boot, last_mode is 0 and lights up LED 10. I hit the reset switch and last_mode is 1 and it lights up LED 11. And every time after that, last_mode is 1. I was under the impression that memory isn't explicitly reinitialized after EXTRF, but it sure seems that last_mode is getting reinitialized every time, and only the increment in the EXTRF elsif is updating it from 0. Is there a trick to ensuring that variables aren't overwritten? It's my understanding that the HLT "bootloader" just flashes the appropriate fuses, so there isn't actually a bootloader mucking around with MCUSR like happens on the ATmegas. MCUSR seems to contain the right bits after PORF and EXTRF are asserted, so I'm getting into the conditionals that I expect.
(Actually, typing this up gave me the idea to monitor last_mode via blinking the appropriate LED, and that confirms that last_mode is getting reset to 0 after I hit the reset switch. Hrmph.)
Any ideas? Googling around has a few suggestions that imply that this ought to work, but none of them are in the Arduino environment, so I half suspect there's some basic assumption stomping on it at compile time.
I've noticed, but haven't bothered to fully track down, that the onboard DC regulator doesn't drop the Arduino to the same power level as the USB-supplied power. I had a project with 4 different thermal sensors - 2 digital and 2 voltage dependent (DHT11 & DS18B20 vs LM35 & something similar), and when the board was running from USB everything agreed, but as soon as I changed to 9v in (or 6v or any of the other source voltages I had) the analog sensors started to skew. I wasn't interested enough to do the right thing and adjust my script by whatever was coming in on AREF, but I suspect something similar is happening here. If you have a multimeter, check the voltage difference between the GND and Vin / 5v pins when the Arduino is on USB versus 9v. My suspicion is that the USB side is feeding your LED 4.5v while the 9v is supplying slightly more than that, causing the changes that I saw in your video. The delay steps seem fine, but the baseline doesn't start at "off" it starts at something which is visible.
Otherwise yeah, slap some serial debugging in there. Note that when testing timing sensitive effects, use the fastest serial speed available - 115200 if you can. Anything slower and you run the risk of your serial transfer overwhelming the timing you are attempting to see.
Diffused are best for message boards, having the widest viewing angle/s. The concave-lens sort are "NOS" point-source, narrow viewing angle. Capturing LED action for youtube can be a challenge - strobe and frame rates, the camera and its features, and so on.
Yeah, I'm totally jealous of Aki's work for The LED Art, his color saturation is beautiful and it's just locked in. Admittedly, using my iPhone as a video camera is one of my bigger limitations, but there's no comparison to this:
This is really helpful! thanks a bunch! Question: you say you've been doing a lot of charlieplexing, I've been having a difficult time grasping the whole idea of coding around charlieplexing. Do you have a sketch or something I could study?
The simplest (useful) Charlieplex sketch I know of it Ben Brandt's - it's what I use for anything under 30 elements since it's just running around in a loop. It has limitations that keep it from scaling too well, but it's pretty clear how it's working:
Effectively you define your port configuration in led_dir and led_out, then you can call light_led with which LED you want to light. But I usually use draw_frame to run over an array of LED brightnesses. So instead of drawing a 4x5 grid of LEDs, I have one running a Tiny85 using Asher Glick's charliecube arrangement in this code:
..which isn't as well commented as it could be, but if you look at the main loop, the first case is pretty straightforward: It draws a random LED in a random color for 100 loops. It's entirely free from strict timing, so it's not too useful when you try to do things asynchronously, but for simple displays it's easy to get up and running.
Once I needed more asynchronous capability (where I can just fire drawing commands off into an array and an ISR handles keeping the display updated), I migrated to Jimmie Rodger's LoL Shield code. The simplest version that I have running is a 30 LED array that plays life and tells the time:
Fundamentally the changes from the Lol Shield product are mostly tied up in the ledMap definition in Charlieplexing.cpp. Each element of the array is the input and output pins for each LED position. If you look into the Rain function, that's a simple way of driving the array - make changes to world, call fade_to_next_frame() to switch active buffers.
The 110 LED arrays in the video are all using the logical extension of the 30 LED code, just tweaked for memory utilization - the LoL Shield code tends to allocate way more memory than it needs, which limits what you can do with a 328:
So I've been building charlieplexed displays and haven't seen a lot of detail on how various LED types perform in display functions, versus acting as indicators or providing lighting. I just finished up my 3rd display using different LEDs and shot video of them together. The video is pretty good, but it doesn't do justice to how different they really are unfortunately. The camera's sensor just doesn't deal with the breadth of exposures as well as a retina does.
Some editorial observations:
1) Water clear LEDs. They're readily available and tend to be the cheapest ones to get in quantity off of eBay. They're exceptionally bright and that tends to be a disadvantage in a display because they're almost too bright to look at. Yeah, careful resistor selection and PWM modulation can take the edge off, but they're still very very bright. 3mm water clear LEDs (not shown) are easier on the eyes and kind of nice in a twinkly way, but they're fiddly to work with since they don't tend to have nice flat bases like 5mm LEDs do, so getting them all lined up and coplanar is a bit of a pain. I've seen really nice things done with them with diffusers in front of the LEDs, though. They also seem to have a bit of a viewing angle issue - if you're right in front of them they're pretty clear, but as you get more off axis, the spilled light tends to turn your display into a blur.
2) Straw hat LEDs. They're slightly harder to get, and the auction pictures make them look more diffused than they really are, but at least the batch I got are all tight little pinpoints of light. It's actually a fairly nice look, and you can view them pretty far off angle without losing too much detail. The ones I have are like normal water clear LEDs without quite so much body, but they still have a domed top. I have some of the other straw hat LEDs where the lens is concave instead of convex and their lighting performance is pretty similar. They're not quite as bright as the water clear LEDs I have, but they're a different color, so it might just be a base brightness difference. Hard to say with how thin the documentation is on eBay.
3) Diffused LEDs. I really like these for display purposes. They're bright enough to be seen in normal room lighting without being so bright that they keep you up at night. I can see them at pretty much any useful angle, too. The only thing I worry about is that they might not be quite bright enough once the display goes into an enclosure, even a clear acrylic enclosure. But I really like the look in displays.
Going forward I figure I'll go with the diffused LEDs or straw hat LEDs for displays, leaving the water clear LEDs for other purposes.
Eliminating the bootloader makes updating the firmware a bit harder, but it also increases the amount of flash you have for your program, as well as removes the boot delay while the loader waits for escape character, letting it know there's new firmware to load via serial.
Yeah, and for reasons I'm not entirely certain of, the bootloader that I'm using through the Burn Bootloader command is the (a?) no-wait bootloader that only enters serial programming mode after a reset. It's disconcerting to use my official Arduino that has a delay on powerup now.
Of course, now that I've re-routed all of my signal lines to the top of the board, I have the entire bottom of the board (more or less) to route an ISP header to. I might just put both headers on the board, but I'd like to keep the no-wait loader I've been using because I ran out of SRAM before I ran out of flash, so the bootloader overhead is in a section of memory I'm not even touching anyway.
I am making a color mixer and fader for RGB LED lighting, and found the boot delay annoying when I powered up the system. Removing the bootloader makes the startup nearly instant.
I use a USB-ASP I got off ebay for a couple of dollars. In reality, it is just an ATMEGA8 running what appears to be a software USB stack and ASP firmware similar to using the arduino as an ISP.
That's the one I'm using too - $5 and it programs ATtinys like a champ without making me rip up my Arduino. Still waiting on my ZIF sockets to make it a little less breadboard-y, but it's a lot simpler than fiddling around with ArduinoISP.
But won't that leave the fuses set to whatever factory default they come in and prevent the bootloader from getting flashed to the chip? Or does part of the ISP upload process set the fuses to what's in boards.txt for the selected chip? My whole experience with ISP so far has been with ArduinoISP and ATtiny85s, this would be my first whack at using it (well, functionally similar anyway) on a 328. I have sufficient flash so the optiboot overhead is negligible, and the possibility of field upgrades using cheap FTDI connectors has a certain appeal.