Posted 1 month ago

AVR Programmer, /HWB, and HWBE

I made a minor error in 1.0 of the circuit. I was so proud of myself for noticing that external pullup resistors were redundant when the AVR’s internal pullups were activated that I neglected to put a pullup on /HWB. This is the pin that, when the HWBE fuse is programmed, should be high to run normal application code on reset, and low to start the bootloader. Instead I’m seeing the bootloader always running on reset, meaning that the BOOT solder jumper does nothing.

This makes sense in retrospect. The datasheet says that all pins return to their default states on reset, and for PORTE pins, that’s tristated. So my /HWB is floating, and the AVR is consistently reading a low logic level.

Adafruit (and software) to the rescue! They modified LUFA’s BootloaderCDC to time out the bootloader after a few seconds. Plus they added a nice breathing LED feature, so at least bootloader mode (even if unwanted) is pretty. This means that on reset, you get both the bootloader and the programmer; you just have to wait a moment for the programmer to appear. This is fine, because for most use cases (plugging in the board to USB) it goes straight to the programmer, skipping the bootloader.

In the next rev of the circuit I’ll add the pullup so that the BOOT jumper does something. But the software change means the 1.0 board is functional. Cool!

Update: I wrote to Atmel Support (knowing that Dean was on duty) and got a marvelously complete response:

Dear Mike,

That is correct; the AVR pins are tri-stated during the reset procedure, and as a result no pull-up is applied to the HWB pin while it is sampled. As a result, you will need to add an external pull-up (or, to invert the logic, pull-down) to this pin to ensure that the correct behavior is applied every time the chip is reset. There is no way to specify that the pull-up is to be enabled during the reset procedure on the HWB pin.

One possible solution to this is to disable the HWBE fuse, and instead program the BOOTRST fuse. This will unconditionally start the AVR’s bootloader every time the device is reset (regardless of reset source). Inside the bootloader as part of the initialization procedure you can enable the pull-up on the HWB pin and sample the value manually, jumping to the user application if the pin is not in the desired state via a software-jump to location 0x0000. An example of this procedure is shown in the LUFA DFU bootloader, when compiled for the XPLAIN board, although this uses an unrelated JTAG pin as the trigger to stay in or leave the bootloader.

Best Regards,
Dean Camera
Atmel Technical Support Team
Posted 1 month ago

AVR Programmer 1.0 is Built and Working

The boards arrived from Dorkbot yesterday. I learned my lesson from last time and assembled all three in parallel (taking the risk that the circuit was bad and that I’d waste 3x the materials). I flashed the bootloader to the first one using the alpha version of the board (in the back with the blue shunt), then self-programmed it over USB with the AVRISP mkII firmware. Final test:

I read the fuses from my Hypna Go Go’s ATtiny13A, and I got the lovely Device signature = 0x1e9007 that seems to play a critical role in many dreams I recall nowadays. Success!

Bringing up the other two boards was a bit more difficult. The first would program and would blink its bootloader status LED, but it wouldn’t program. A cold solder joint on the ‘32u2’s core GND pin was the cause. The last board was a more serious case: the ‘32u2 got hot when I plugged in the USB, and other than being ISP-programmable, it was dead to the world. I never found the short, but I did scrub off the flux more carefully, and I resoldered a couple capacitors that looked slightly suspicious, and when I plugged it back in again, it was fine.

Next steps:

  • Validate that the new HWBE jumper works.
  • Port over the JTAG Whisperer.
  • Expose the USB-TTL serial functionality.
  • Fix a few layout issues (obscured labels, component placement that is inconvenient for assembly).
  • Switch to a version of the USB socket that has pegs. I can already tell a high-use application like this is going to need a little more strength than just SMD solder pads.
  • Replacement of the current-limiting resistor on the LED. Someone please remind me why I picked 1K ohms. My gorgeous purple LEDs are hardly visible!

(Update: linked to this post on Reddit.)

Posted 1 month ago

AVR Programmer, AVRISP mkII: About a bug

I had a good debugging session over the last few nights and want to write down my notes here.

The AVR Programmer initially worked with a target ‘328p, but it hung when programming a second build of the board, and then again on a particular ATtiny13A that I was using for the Hypna Go Go. Oddly, it worked for another ‘13A that I was using on the same project. The board was flaky, and as a result, I couldn’t keep my promise to myself to never again ISP-program another AVR without a programmer I’d built myself.

A few nights ago, while getting ready for the latest and greatest version of the board to arrive from the factory, I decided to take a look at what was going on. I got out my Saleae Logic and watched the SPI traffic. Perfect… except that the target ‘13A never responded on MISO. I swapped in a known-good programmer, confirmed it worked, but then saw that the logic signal patterns were identical. The target wasn’t responding, but the known-good programmer was programming it!

I suspected bad logic probe connections… nope. They were fine.

Getting a bit frantic, I zoomed out in the Logic app, and immediately figured out why the target wasn’t responding. The first cycle through the initialization sequence (the only cycle I’d been examining), it always failed. But the second cycle succeeded, and I never saw this until I zoomed out.

Next question: why was the known-good good? I re-read the datasheet for the ‘13A and saw that if the programmer couldn’t guarantee SCK was low on target powerup (which indeed applied in both my and the known-good programmer cases), an alternate way to get into programming mode was to pulse /RESET high for a bit. I could see the known-good doing this between the first bad and second good cycles, and my firmware was doing the same thing, so what was the difference?

Back to my programmer under the logic analyzer. Zoom out… and see that in fact /RESET was staying low consistently. Aha! That’s the problem. But why was it happening?

It turns out that the LUFA code doesn’t pulse /RESET by sending it high. Instead it tristates the pin. This makes sense because you want your programmer to disconnect from the target when you’re done so that /RESET can go back high on its own. This is fine, except that my programmer has a 74AHC125 buffer between the ‘32u2 and the ISP outputs, and a tristate output entering the buffer leaves as a low logic signal. This is why my programmer wasn’t pulsing /RESET, and it’s why programming sometimes worked if the powerup sequence happened to be right, or if the chip in question (such as most 328p’s or some 13A’s) happened to be a more tolerant sample.

Once I understood the problem, the fix was easy. Change LUFA to pulse /RESET with explicit logic levels, and insert buffer enable/disable code at the appropriate places. So far, it’s been running flawlessly.

Posted 1 month ago
Posted 1 month ago

Hypna Go Go Results, Day Nine

Regular readers will recall that I haven’t had much hypnagogic luck with my blinking LEDs. I theorized first that the lights weren’t bright enough, and second that I wasn’t remembering my dreams no matter how fantastic they were turning out to be.

Theory #1: LEDs too dim

I found some better bulbs: water-clear and quite a bit brighter. These are now so bright that they sometimes wake me up. I’m going to try putting some masking tape over them to diffuse the light.

Theory #2: Remembering nothing

This is likely the real problem. I just don’t remember dreams very well. This is probably because I’m very alarm-driven in the morning and because my kids deeply enjoy asking me questions like “Dad, when’s breakfast?” while they know perfectly well that I’m still asleep. My dream consciousness is quickly shoved into oblivion every morning.

Oneirologists (yes, they are a thing) recommend keeping a dream journal to improve dream memory. Like most who fail at this endeavor, I first rejected that idea the same way I reject all diaries (girl stuff, not my style). After a few nights, though, I developed a sneaking suspicion that the lights were affecting my dreams, just that I couldn’t remember it. I admitted that memory was a deal-breaker. So I started describing my dreams each morning to my wife. A few days ago I put a real pen and paper by the bed and have since written down three detailed dreams.

Now that I have gone through the exercise, I see the value. The problem I had with keeping a dream journal was that I thought the purpose was dream analysis, which I honestly didn’t care about. But in fact, that’s not the purpose at all. Rather, by training your mind to recall dreams and to place dream events into your real, normal long-term memory, you gain the ability to classify dream experiences as dream experiences. This is different from how your mind normally experiences dreams: “Here I am in a small boat in the middle of the ocean, with nothing but a toy and a cat from my childhood. Seems legit!”

By recalling dreams while awake and conscious, you can train yourself to recognize dreams as dreams after the fact: “New rule: when I’m inexplicably in the middle of the ocean, it’s probably a dream.” Presumably, soon my unconscious self will use the same skills to distinguish dreams from reality, but at the time the dream is happening. If that alone isn’t enough to bring myself into dream awareness, then the blinking lights ought to give me the kick I need to do it.

Posted 1 month ago

OK Wake

OK Wake is a project for a friend whose kids are old enough to get out of bed on their own, but not yet old enough to read clocks, meaning that they tend to start waking up the whole house at 4am.

As it gets close to wake-up time, the device starts gently blinking red. At the designated hour, it changes to green. That’s about it!

The circuit is my first using a real-time clock. I’ll be drawing on my power management experience from the Hypna Go Go. I was going to use a surface-mount ATtiny, but I ran out of pins for ISP, so rather than trying to get clever with jumpers, I made it socketed instead.

I want to keep the software insanely simple. I hope it requires zero configuration; it’ll just do its thing every day for the couple years it will take before the kids learn to read. In the event the clock does need to be set, I think I can figure out something mildly inconvenient but simple involving the button (like pressing it for one second to reset it to 7pm, which takes care of timezones within the U.S., and handles any accuracy issues over the months and years). This scheme could take care of Daylight Saving Time; either you need to press the button twice a year, or else pressing it resets it to 7pm of the current day, and the RTC still tracks DST switchovers.

Posted 1 month ago
Posted 1 month ago

AVR Power Management

I designed the Hypna Go Go schematic and board quickly in one evening and sent it to be manufactured that night. The next day I realized I’d forgotten to add a power switch, meaning I’d have to remove the coin-cell battery every morning.

Or I could solve the problem in software. That’s what I did.

You can read the code for yourself, but I took advantage of the fact that I already had a momentary button between ground and PB4 on the ATtiny for switching immediately into dream mode. The updated firmware starts out by turning off all unneeded peripherals, such as the ADC and BOD, then turning on a pin-change interrupt on PB4. Then it switches to the PWR_DOWN sleep mode. In other words, putting in the battery starts up the device in a switched-off state.

Pressing the button fires the interrupt, effectively turning on the device, and it does all the setup it would have done normally. I refactored the button code to manage all the relevant state inside the pin-change interrupt service routine. Tapping the button goes straight into STATE_DREAM as before, but holding it down for two seconds goes back into PWR_DOWN sleep mode, after a blink sequence to confirm that it’s really shutting off.

I haven’t yet figured out how to measure microamp-level current draw in this circuit, but if I’m doing it correctly, then I’m probably drawing less than 1uA in switched-off state. Even for a 40mAh CR1220 coin cell, that’s a few years, and it easily outweighs the cost and complexity of adding a physical slider switch.

Posted 1 month ago

The Hypna Go Go

I’ve seen these crazy lucid-dreaming goggle projects for years, but recently stumbled across a really simple one on Instructables. I happened to have all the parts around the house, so I made one. I’ve since improved the firmware and designed a real circuit board that is off at Laen’s. The improvements are that the circuit board is smaller, and the firmware is lower-power and better synchronized with a typical 8-hour-sleep REM schedule.

As noted in the GitHub project, it hasn’t worked for me over three nights of testing. I have two theories.

One theory is that the lights aren’t bright enough. I used some very old red LEDs with about 140 ohms of resistance. They’re completely visible to me in my tests, but it might not be enough for my sleeping brain to notice.

The other theory is that it actually is working, but I’m not remembering any of it when I wake up. This is a distinct possibility because I almost never remember dreams. They say that teaching yourself to remember your dreams is the first step in improved dream awareness. I’ll work on that.

Meanwhile, here’s a picture of what I built, and you can also check out the EAGLE files and the AVR code.

Posted 1 month ago

nRF24L01+

I wonder why more makers don’t use the nRF24L01+ for wireless design. It’s almost free, it’s super-low power, it’s easy to use with SPI, it’s 5-volt tolerant, it’s plenty fast for 8-bit applications, and it just plain works. It might be because it’s available only in QFN, which looks scary.