-
Maker Faire San Diego, Oct 3&4
09/14/2015 at 02:14 • 2 commentsJust got confirmation!
Hope to see you there, San Diego friends.
-
Hackaday Prize Best Product Finals info
09/21/2015 at 20:42 • 0 commentsThe Prize rules are somewhat particular about requirements, so I figured a dedicated project log that puts everything in one place might be helpful.
Video
Create a video, between five (5) minutes and ten (10) minutes in length, that shows a completed, working prototype with a market-ready product design/look and feel. The video should describe the problem it is solving and demonstrate how it facilitates the solution. The video does not need to be “studio quality,” but it should “sell” the project to non-technical viewers. Upload the video to YouTube or Youku and tag the video with the keyword: HackadayPrize, finals.
Project ProfileLink to the new video.
See above. It's also the bottom link on the project sidebar.
Update and add detail to info entered at the previous stages.
We've updated the Details section on the main page; that's probably your best bet to see exactly where the project stands today. A good deal has happened since the first THP2k15 deadline (8/17/2015):
- We created and shared a lot more NeuroBytes operating and test modes.
- We got lots of excellent feedback on the platform from the Game Maker's Guild.
- We interfaced NeuroBytes with a MeArm and a multichannel touch sensor [video].
- We were accepted to display at San Diego Maker Faire, 10/3 - 10/4.
Show at least twelve (12) Project Log updates.
If you want a complete and unfiltered history of the project, your best bet it to start at the beginning.
Post a components list that is complete with a bill of materials for one unit.
See the main project page, or click through to the components list. This includes everything needed to build one NeuroBytes v04 board and one Axon. You can also check out the BOM on GitHub, which adds in a few more Axons and includes old product links.
Post reproducible build instructions.
See the main project page, or click through to the build instructions.
Document complete schematics.
See this image from the gallery, or grab the Kicad files from the GitHub repo.
Post high resolution photos of the project inside and out. Include Gerber files (req - RS274 / RS274X), STL files (opt), netlist (opt), nc drill files (req - human readable), ODB++ (opt), STEP (opt), PCB files (opt), or any other design files.
Grab the Gerbers from the GitHub repo. Other design files (firmware and hardware) are elsewhere in the same GitHub project.
-
Joe and Zach Meet for the Second Time
10/06/2015 at 10:34 • 2 commentsWorking 1000 miles apart isn't so bad with stuff like Google Video Chat. But it was still great to spend the weekend at San Diego Maker Faire!
If you missed the show, we'll be back next year--it was an amazing experience in a beautiful city!
-
v05 Prototype
10/31/2015 at 06:12 • 0 commentsMore to come...
We're thinking about a different lighting scheme, one that involves a bunch of tiny LEDs. Green LEDs. Tiny green LEDs. I've never worked with 0402 stuff before. It's easy to lose (shown photographed through a loupe):I ordered 25 LEDs, lost/destroyed the first couple, then tried to connect them to a dead-bug shift register (top right). During testing I fried a bunch of the LEDs, and the Dremeled trace work wasn't consistent enough to really function, so I tried again (bottom). Dead-bug plus 0.65mm pin spacing was tough to get working. Also shown: tiny connector!
Time to shift gears, skip the shift register (note the attempted dead-bug ATtiny88, also abandoned), and mount the microprocessor right-side-up. X-acto trace time!
This chip is a bit more forgiving at 0.80mm, but I still had trouble with alignment. To make sure the pins lined up, I soldered the device halfway to the board and carefully cut the remaining traces using the installed chip as a guide. Not shown: an unbelievable number of continuity tests:
After finally getting the damn processor to listen (more continuity checks!), I toggled the LEDs on and hit a few snags. One was wired to the RESET pin (dumb) so I temporarily disconnected it, and another had a short. But more importantly... one was also the wrong color:
The LED worked but the single yellow element really bothered me. I was (and still am) also bothered by the fact that I pulled all the LEDs out of the same tape, meaning there was a sorting issue at the factory. At this point the LEDs I hadn't soldered down had pretty much all evaporated off my workbench due to moving air currents, so I had to desolder one from the other ring (which took 5 tries to get right). Finally done:
To do: dendrites, axons, more indicators, and a bit more time defluxing. Also programming, I suppose.
-
Prototype gif + concepts for v05
11/24/2015 at 04:00 • 0 commentsI brought the v05 prototype to the Superconference and briefly showed it during my talk (then proceeded to zip-tie it to my badge and carry it around for the rest of the evening). If you missed that, here's a quick clip of the board in "neuron demo mode":
So... the finished product won't have a bunch of DIP switches on board, or a 0.1" spacing ISP header, or a bunch of varnished jumper wires everywhere. The blue LED (which is also red sometimes) won't stay on all the time; these indicators will be used to show which dendrites are excited or inhibited, probably pulsing with brightness proportional to input weighting.
Beyond the LEDs, that's the other big change--input weighting. I'm also planning to use 4-pin connectors, so we can implement a backpropagation mode that actually changes individual dendrite weightings based on sequential firing. We've got a bunch of other ideas similar to this, but operating modes really are the key bit. Another shot, including the completely useless (well, beyond its current use) USB power adapter I put together:
I used the RJ11 (phone handset) cord because it's the only cable I had on hand that (a) was multi-conductor, and (b) had an O.D. close to the JST connector spec. I tried my usual rainbow ribbon cable and it split the connectors apart. I kept the phone plug on for, uh, modularity? Seemed silly to just cut off a perfectly good connector...
Briefly, here's where the v05 schematic stands:
It's anything but finalized, so I'm not quite ready to push this to the repo as a final product. In any case, I really like having eight indicator LEDs, and we both feel that six dendrites and three axons is ideal. I want to do some fancy dimming stuff with the LEDs so I'd prefer to avoid the complications related to multi/charlie-plexing, so I dropped a few of the R/B dendrite LEDs in favor of membrane potential indicators. This will actually work pretty well--we're planning to group pairs of dendrites together for one of our operating modes, so sharing a single R/B LED between two inputs makes sense. I also switched to a bunch of resistor networks, because 25 0402 resistors seems like a super pain in the ass to deal with.
Layout is still a work in progress. As promised, the new version is going to look more neuron-like than the square boringness that was v04. Further work will likely wait until after turkey day, so stay tuned...
-
v06 boards off to fab _soon!_
12/07/2015 at 21:38 • 0 commentsThey're different enough from the v05 prototype that I decided to iterate the version number.
OSHpark renders:
Lots of new features:
- red/blue dendrite indication
- bargraph membrane potential indication
- surface mount connectors with finer pitch (1mm)
- right-angle connectors for axon terminal
- three axon connectors (vs 1)
- mode selection
- adjustable weighting/summation between dendrites in the same group
- pogo programming
- swanky logo/graphics
- directional board shape
- backpropagation
- multiplexed LEDs
- compatibility with v04 (with suitable adapters)
Price (obviously) has gone up, as has complexity. Some of the features will take significant effort to implement in firmware. Either way, we are quite excited. More to come!
-
FUNDING SECURED!
12/17/2015 at 21:03 • 10 commentsWe applied for a Phase I SBIR from the National Science Foundation back in June to develop the NeuroBytes platform and get it into a classroom. Today we found out that we've been awarded the grant! That means as of 1/1/2016, we'll both be working full time on this project! BOOM!
So yeah, excitement. I'm going to keep using this project page to document all the details related to the platform, so stay tuned. v06 boards just shipped from OSHpark!
-
v06 prototypes (partially) working!
12/19/2015 at 17:05 • 5 commentsI'm still waiting on a few parts (namely 0402 dropping resistors for the LEDs), but I got one v06 prototype partially assembled last night--and I can talk to the ATtiny88, so I must have done something right with the design!
You may have noticed the six pads on the back of the board design--I wanted to try pogo-style programming, since that's what we'll use when we ramp production up a bit. I deliberately made the pad locations symmetrical along the long axis of the board, intending to use one of the six prototypes as a base for programming (along with some hastily soldered together FR-4 as an alignment rig):
[note: someone at the #Hackaday SuperConference 2015 gave me a few googly eyes that made their way onto my USBtinyISP. Who was that? Thanks!]
The note already tells you something is wrong; during handling I managed to snap off one of the pogo pins. Turns out 1.5mm diameter pads break pretty easily. It's the MISO pin, so I re-purposed the ground plane and added a "splint":
Hilarious but ultimately ineffective--soon after taking this picture I snapped another pin off. Lesson learned--use insertion-mount pogo pins and take the time to make a custom carrier board! In any case, I decided to mount the pins directly to the FR-4; I had to tweak the alignment of a few to get a reliable connection, but this setup worked. I made sure to give each pin a generous copper pad so it wouldn't break off as easily:
I also scavenged a NeuroTinker logo off the scrapped board. The solder mask pullback + ENIG copper logo turned out pretty well, so I figured it was worth highlighting.
Oh yeah, and I didn't remember to implement one of the important lessons I learned when I put together v04: 4-pad SMD LEDs are a PITA to hand-solder and including a bit of extra pad goes a long way. The red/blue dendrite LEDs check out with the continuity tester, but we'll see if they actually work...
-
v06 MP indicator fading
01/06/2016 at 15:48 • 0 commentsYesterday I put together a few functions that fade the twelve membrane potential LEDs using 6-bit BCM at 160 Hz:
A good deal of this was developed at various Minneapolis coffee shops filled with curious patrons asking me questions about green LEDs. I was happy to take a few tangents to discuss neuroscience. As demonstrated above, flicker is noticeable when the NeuroBytes are waved back and forth rapidly, but I don't think it's too bad; after all, these devices will generally be used on a static surface. 160 Hz is a decent bit faster than those annoying LED Christmas lights, after all.
The functions started with Nigel Batten's excellent BCM example. I liked how he used the 'tick' counter to trigger stuff in the main loop from the ISR, keeping the interrupt stuff brief. Most of the other code is different, as I'm dealing with a 3x4 LED matrix spanning three different I/O ports (A, B, and D) and didn't use a pre-encoding function. I'm not going to add this firmware to the GitHub repo at this point as it's far from finished/debugged, but I'm posting it here if anyone has any comments or wants to use it for something else (it's all GPL v3). My code has slightly improved since the v04 days, but I'm still learning the basics re: bit manipulation and speed. I also added a sweet ASCII diagram for I/O reference.
(note: I didn't add any commentary after the code block, so feel free to stop reading this post now)
/* NeuroBytes v06 test program Fading MP LEDs via BCM, attempt 2 Copyright 2016 by Zach Fredin zach@neurotinker.com This file is part of NeuroBytes v0.6. NeuroBytes v0.6 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. NeuroBytes v0.6 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with NeuroBytes v0.6. If not, see <http://www.gnu.org/licenses/> */ #include <avr/io.h> #include <avr/interrupt.h> /* /\ / \ / \ / \___________________________________ \ \ \ NeuroBytes v0.6 \ \ \ \ D D D D D D D D D D D D D A | | 1 2 3 4 5 6 7 8 9 9 1 1 1 P | / 0 1 2 | / / / / / ___________________________________/ \ / \ / \ / \/ */ /* Membrane potential brightness array Array dimensions: MP_brightness[cathode][anode] IND-A1 IND-A2 IND-A3 IND-C1 D1:[1][1] D5:[2][1] D9:[3][1] IND-C2 D2:[1][2] D6:[2][2] D10:[3][2] IND-C3 D3:[1][3] D7:[2][3] D11:[3][3] IND-C4 D4:[1][4] D8:[2][4] D12:[3][4] */ volatile uint8_t MP_brightness[4][3] = { {1,31,15}, {3,63,7}, {7,63,3}, {15,31,1} }; volatile uint8_t g_tick = 0; //flips to non-zero when time to update (via ISR) volatile uint8_t g_bitpos = 0; //which bit is currently being checked volatile uint8_t MP_currentAnode = 0; ISR(TIMER0_COMPA_vect) { /* This interrupt service routine makes ticks fire at exponential intervals. It also dwells on each interval for three (hopefully) equally-spaced iterations to set the three anodes. */ g_tick = 1; //fires tick in main loop TCNT0 = 0; //resets Timer/Counter 0 MP_currentAnode++; //iterates anode if(MP_currentAnode > 2) { //go to the next bit if we've hit all three anodes MP_currentAnode = 0; OCR0A <<= 1; //double the delay g_bitpos++; //move one bit left if(g_bitpos > 5) { OCR0A = 1; //reset the compare register to timer refresh rate (see TCCR0A) g_bitpos = 0; //go back to the LSB } } } void systemInit(void) { /* set up Timer/Counter0 */ TCCR0A |= ((1<<CTC0) | (1<<CS02)); //CTC, clk/64 TCNT0 = 0; OCR0A = 1; //presets Output Compare Register A TIMSK0 |= (1<<OCIE0A); //enables Output Compare Match A Interrupt /* set up membrane potential indicator LEDs */ DDRA |= (1<<PA3); DDRB |= ((1<<PB7) | (1<<PB6) | (1<<PB0)); DDRD |= ((1<<PD5) | (1<<PD6) | (1<<PD7)); /* preset all ports low */ PORTA = 0; PORTB = 0; PORTD = 0; /* misc */ sei(); //enable global interrupts } void MP_off(void) { //sets all cathodes, clears all anodes PORTD |= ((1<<PD5) | (1<<PD6) | (1<<PD7)); PORTB |= (1<<PB0); PORTB &= ~((1<<PB7) | (1<<PB6)); PORTA &= ~(1<<PA3); } void MP_setAnode(uint8_t anode) { //sets designated membrane potential anode switch(anode) { case 0: PORTB |= (1<<PB7); break; case 1: PORTB |= (1<<PB6); break; case 2: PORTA |= (1<<PA3); break; } } void MP_clearCathode(uint8_t cathode) { //clears designated membrane potential cathode switch(cathode) { case 0: PORTD &= ~(1<<PD5); break; case 1: PORTD &= ~(1<<PD6); break; case 2: PORTD &= ~(1<<PD7); break; case 3: PORTB &= ~(1<<PB0); break; } } int main(void) { systemInit(); uint8_t MP_currentCathode; for(;;) { while(g_tick==0); { /*blank idle code waiting for ISR */ } g_tick = 0; //consumes tick when routine starts MP_off(); MP_setAnode(MP_currentAnode); for (MP_currentCathode = 0; MP_currentCathode < 4; MP_currentCathode++) { if ((MP_brightness[MP_currentCathode][MP_currentAnode]) & (1<<g_bitpos)) { MP_clearCathode(MP_currentCathode); } } } }
-
ATtiny Izhikevich(ish) Dynamics, part one
01/28/2016 at 20:25 • 0 commentsI've been slacking on updates--turns out when you get to work on a project full time, it doesn't make logs magically appear. In any case, this log post will focus on one thing: improving the core NeuroBytes firmware. I'll bring ya'll up to speed on other stuff in the next few weeks.
If you ever took a look at the v04 code, you may have noticed that the neuron membrane potential decay algorithm was quite simplistic:
if (potentialTimerCounter >= potentialTimerOverflow) { decayPotential = (decayPotential * 95) / 100; }
This pretty much takes the current value and multiplies it by 0.95. There were a few other snippets here and there that did stuff too--if the current potential was over 100, for example, the code called that a "fire", immediately dropped the membrane potential by _a lot_, and made the LED blink white. The resultant boards looked reasonably correct, but the model didn't respond quite as expected when stimulated at higher levels. Neurons also fired _immediately_ rather than ramping up over time. Other issues included an unacceptably low refresh rate, occasional atomicity problems, and general inflexibility--it wasn't possible to change individual dendrite weighting, for example. Time for a rewrite.In 2003, Eugene Izhikevich published a paper describing a computationally efficient method for simulating a variety of biological neuron types in software. His results were impressive: using a consumer-grade 1 GHz desktop PC, he was able to simulate a 10,000-element spiking cortical neuron network in real time with 1 ms clock resolution. A few years ago, @Bruce Land successfully implemented Izhikevich's model on an FPGA in his #Spiking neural net simulated on FPGA project.
Electronic version of the figure and reproduction permissions are freely available at www.izhikevich.com
You should probably stop reading this now and go read Izhikevich's paper, and then check out Bruce's project. In a nutshell, the model uses a pair of differential equations to keep track of membrane potential (v) and membrane recovery (u), along with a limit check that resets the model when the neuron fires. a, b, c, and d are parameters related to the specific type of neuron being modeled, while I is the cell's constant current input. As far as I can tell, these parameters were determined empirically based on observations of actual neurons, and the resultant model is quite accurate.
The first step was to recreate Izhikevich's model in a spreadsheet so I could wrap my head around the equations. This is what I eventually came up with, graphed over 0 < t < 500 ms:
The sheet is actually pretty fun to putz around with--you can change the parameters as Izhikevich suggests to emulate different types of neurons, such as fast spiking:I also broke out I, as well as the original coefficients Izhikevich used in his differential equations; I called them E (the square coefficient), F (the linear coefficient), G (the offset coefficient), and H (the reset voltage threshold). They were also fun to putz with, although pretty much every minor change resulted in something like this:Disastrous results from a tiny change, as you can see. Maybe I shouldn't mess with the coefficients.So what's the issue? Why am I messing with the coefficients? Why not just copy the equations directly from LibreOffice Calc into VIM and call it a day?
In a word, speed. Remember, I'm trying to reduce flicker while PWMing three LED elements using an 8 MHz 8-bit microcontroller. Based on the LEDs I'm using and the desired dimming range (and a lot of waving test boards around), I need to update the LEDs every 30 us or so--that's 240 clock cycles. Since the ATtiny doesn't have anything resembling a floating point unit, everything also needs to be worked out in integers.
I tried adding int() tags in various spots in the equations, but I didn't get very far. The first coefficient divides the square of v by 25, and rounding the quotient inevitably caused huge errors. Once I started introducing these errors--even when I managed to make them pretty small--I began to realize just how delicate the balance between a, b, c, d, E, F, G, H, and I really was. Time for another computer program! Here's a test version that uses floating point math to prove out the concept:
... results:Yeah, I totally was going to try (E = 0.031384, F = 4.654088, G = 153.545868, H = 75.376656) next!The program is actually pretty simple. It selects four random coefficients within a predefined range, runs through the entire 0 < t < 500 sheet using Izhikevich's original equation format (and standard spiking neuron parameters), checks the "fit" of the result, and stores the best "fit" coefficients until it's run through an unreasonable number of iterations. It's a brute force approach that works well enough for floating point math, as shown above.
To produce AVR-ready code, I forced the program to use integers in its calculations. I decided to change Izhikevich's original equation a bit to hopefully speed up the calculation--namely, I changed E, a, and b to bitshift operations, meaning they're restricted to various n values in 1/(2^n). I also set up boundary conditions that prevent 16-bit signed integer overflows. Here's what I (eventually) came up with:
It's far from perfect, but the important dynamics work properly--namely, changing the value of I causes the fire rate to increase or drop to zero, and there is a distinct (although not as clear as in the original model) inflection point before each spike. You can see a few "known good" coefficient/parameter sets I came up with--getting to these required fiddling with fitment weights quite a bit, so I wrote 'em down whenever they worked decently well. If you're curious/bored/etc, the complete program is here.
You'll also notice that I left a bunch of new parameters on the screenshot above, along with a second plotted line--those are part of the fitment parameters. The program selects a series of points on the membrane voltage plot where it thinks the neuron experiences an action potential; this is based on the rate of change of this value (the "slope threshold"), and defines the linear and firing regions. The "firing?" line helped me quickly select good slope threshold values. Once this point is selected, the program calculates four parameters, averaged across 0 < t < 500:
linear region slope avg (0.252)
linear region range pct (0.180)
fire ratio (0.132)
number of firings (6)
Combined, these four parameters roughly describe what a neuron membrane potential waveform should look like; the ideal values from Izhikevich's regular spiking neuron are shown above in parentheses.
Up next: implementation in AVR-C. Which is done and works rather well, but I have already written far too much for one log update.