-
Neuron Development: v0.4 part 6: Mass Production
12/08/2014 at 00:13 • 2 commentsNeuron production has begun. This is my first foray into reflow work, so there has been a bit of a learning curve. Here, I made two sticks of four Neurons each and uploaded a test program to light the LEDs up white:
Next, I tried doing eight at a time:
Many observations:
- Solder mask is amazing. I'm hand-applying solder paste from a syringe, giving me inconsistent and sloppy results prior to placing components--90% of the time, it doesn't matter. Bridges seem to magically fix themselves in the oven.
- I should have sprung for a stencil. Seriously, hand-applying solder paste is tedious and frustrating.
- The oven is decent, but not great. Some of my Neuron boards have gotten a bit discolored from the heat while I reset the cycle to ensure other sections fully reflow; the lack of convection fan means temperature stratification is pretty severe. It works, but requires a close eye and a hand on the 'add time' button.
- Hand soldering the connectors takes time but isn't too unpleasant. The headers friction fit nicely into the board so I don't need to bend leads to hold 'em in. After soldering I generally clip the leads as close to flush as possible--probably a bit more than I should for maximum structural integrity, but I don't want the bottom of the boards to be too sharp.
- I've made a lot of Neurons at this point--probably 70+, although some of them are with Andrew in NYC and another batch are with a different friend for some testing. I haven't kept great production records, but generally speaking I'm running around 85% first-round yield, with another 5-10% recoverable using hand rework (generally to fix one of the LED pads not quite connecting right). The units that never work are usually the result of a stupid error (I installed a number of ATTinys backwards) or a huge amount of excess solder gumming everything up.
Up next: firmware!
-
Neuron Development: v0.4 part 7: Firmware
12/12/2014 at 06:51 • 5 commentsThis is important: Zach will never be a skilled programmer. I can bang out half-functional (albeit inefficient and buggy) code when I need to, but it usually involves a lot of cursing and frivolous Google searches. This being my first foray into AVR-C is no exception, so bear with me. Constructive criticism is encouraged.
A few weeks ago I discussed Neuron v04's circuit design and board layout; when I added that project log, I also added a link to the Neuron Github repo which includes both hardware AND software stuff. I've been really bad with revision control for this project, so with any luck publishing the repo will force me to use good practices when updating the firmware. Seriously--the code is pretty much identical to the contents of a folder called 'v04test7' that was buried in a series of Dropbox directories; I only chose it because the mysteriously named 'v04test8' and 'v04test9' had some undocumented bug that I couldn't figure out.
Originally I tried posting the code as-is using the 'code snippet' function, but that doesn't seem to respect tabs (at least in this Ubuntu 14/Firefox 33 combo) which made it pretty hard to understand. As such, I'm going to go through the main runtime firmware here in its entirety, replacing the inline comments with a more in-depth discussion where it seems to make sense. Note that <code> precedes //comments in sections with multiple snippets.
Licensing
/* Copywrite 2014, Zach Fredin zachary.fredin@gmail.com This file is part of Neuron. Neuron 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. Neuron 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 Neuron. If not, see <http://www.gnu.org/licenses/>. */
GNU GPL v3 blah blah blahLibraries
#include <avr/io.h> #include <avr/interrupt.h>
Pretty basic. We need to send signals to the chip through its I/O lines, and we interrupts to work for the inputs.
Variables
int16_t ledGreenfade = 1; int16_t ledRedfade = 0; int16_t ledBluefade = 0;
LED brightness variables, scaled from 0 (dimmest) to 100 (brightest). I don't quite recall why I made these 16-bits; probably to fix a pesky error. Also, the green LED is initially set on (but very dim) which isn't too relevant, since these values will be overwritten as soon as the main program starts.uint8_t debounceValue = 5; uint8_t exDebounceCount1 = 0;//excitatory 1, which is K1, pin 8, PA5, and PCINT5. uint8_t exDebounceCount2 = 0;//excitatory 2, which is K3, pin 10, PA3, and PCINT3. uint8_t exDebounceCount3 = 0;//excitatory 3, which is K5, pin 12, PA1, and PCINT1. uint8_t exDebounceCount4 = 0;//excitatory 4, which is K6, pin 13, PA0, and PCINT0. uint8_t exDebounceCount5 = 0;//excitatory 5, which is K2, pin 9, PA4, and PCINT4. uint8_t inDebounceCount1 = 0;//inhibitory 2, which is K4, pin 11, PA2, and PCINT2.
Debounce counter limit and individual debounce variables for each of the six inputs; I wanted to keep these separate since I didn't want to invalidate quickly occurring pulses on two different inputs (just a single input). Time units are in ms. Yeah, this could probably be an array.int16_t potentialTotal = 0; int16_t inGroundState = 0; int16_t inGroundStatePrevious = 0; int16_t exGroundState = 0; int16_t exGroundStatePrevious = 0; int16_t decayPotential = 0;
These keep track of the current membrane potential of the Neuron. I track the excitatory and inhibitory portions of this value along with a decay multiplier separately, along with previous values for inhibitory and excitatory potential.uint8_t potentialTimerOverflow = 5; uint8_t potentialTimerCounter = 0;
Uh.. to be commented later.
uint16_t timer1Overflow = 10;//FAST loop overflow uint16_t timer2Overflow = 800;//SLOW loop overflow uint16_t timer2Counter = 0;
Timer variables. timer2 is nested within timer1, and timer1 is tied with the system clock. Since I'm running these (currently) at 8 MHz, timer1 should click over at 800 kHz and timer2 should run at 1 kHz. My 'scope seems to confirm that, although I should probably check again at some point. AVR timers are confusing.uint8_t inputMagnitude = 70;//amount each input increases/decreases potential uint8_t inputStatus = 0b00000000;//current input status (read when stuff changes!)
inputMagnitude, as commented, shows how much each excitatory or inhibitory pulse changes the current membrane potential of the Neuron (with +100 assumed to be the action potential threshold). inputStatus--I like to write out bytes when each bit refers to something because it's easy to quickly understand. I suppose that isn't a great way to learn hex. In this case, I'm setting the inputs low for initialization.uint8_t fireTimerOverflow = 2;//how long should LED pulses last? uint8_t fireTimerCounter = 2; uint8_t fireDelayOverflow = 20;//after firing, how long until sending a pulse? uint8_t fireDelayCounter = 0;
These variables deal with action potential events and are timed in milliseconds (they're part of the timer2 loop). 'Firing' means flashing all LEDs at once at full brightness, and the delay shows how long to wait until sending a pulse down the axon. I'm not sure that's working quite right, because I'm pretty sure my Neurons aren't updating at 50 Hz. Hmmm...Interrupt Service Routine
ISR(PCINT0_vect) { //interrupt svc routine called when PCINT0 changes state //note that this is different than the ATtiny45 version inputStatus = PINA; }
Any time stuff changes on the input pins (they're covered by PCINT0_vect), I read their current values into the inputStatus variable and return to the current position in the program. Yay interrupts!LED update function
void updateLEDs(uint16_t Counter, uint16_t Red, uint16_t Green, uint16_t Blue) { if (Counter >= Green){ PORTB |= (1<<0);//wahoo, bitwise logic! turns //the green LED on (low) //for the first part of the //PWM waveform } else { PORTB &= ~(1<<0);//more bitwise logic. turns //the green LED off (high) //for the second part of the //PWM waveform. } if (Counter >= Red){ PORTB |= (1<<1);//see above. this could //probably be simplified into //a swanky function of some //type. } else { PORTB &= ~(1<<1); } if (Counter >= Blue){ PORTB |= (1<<2); } else { PORTB &= ~(1<<2); } }
So... I needed to run my main program code pretty fast, but I also wanted PWM fading on each LED channel. Also, Neuron color fading isn't really linear across the full range of membrane potential; when the value is below zero the LED fades from green towards blue, and when above zero it fades from green towards red. This function is intended to be called during the fast loop--the first argument (Counter) says where you are in the PWM waveform, while the next three arguments (Red, Green, Blue) says how long each color should be high for each part of that waveform. Everything else is unnecessary comments, unoptimized code, and flipping bits on PORTB (where the LEDs are the three least significant bits).System Initialization
void SystemInit(void) { DDRA = 0b01000000; //IO config: PA0-5 in (dendrites), PA6 out (axon) PORTA = 0b00000000; //Turns off pull-up resistors on dendrites, sets axon low DDRB = 0b00000111; //IO config: PB0,1,2 out (LEDs), all others in PORTB = 0b00000111; //Sets PB0,1,2 high to start (LEDs off). TCCR1B = 0b00000001; // sets up a timer at 1MHz (or base AVR speed) sei(); //enable all interrupts: same as changing bit 7 of SREG to 1 GIMSK |= (1<<4);//sets the general input mask register's 4th bit to 1 //to activate the PCIE0 interrupt stuff PCMSK0 = 0b00111111; //sets the six dendrites to active hardware interrupts (0-5) inputStatus = PINA; exDebounceCount1 = debounceValue; exDebounceCount2 = debounceValue; exDebounceCount3 = debounceValue; exDebounceCount4 = debounceValue; exDebounceCount5 = debounceValue; inDebounceCount1 = debounceValue;
The comments are pretty reasonable here. DDRA/PORTA are header connectors (second most significant bit is the axon), while DDRB/PORTB are the LEDs (well, at least the three least significant bits). OH YEAH, and the LEDS are wired with a common positive terminal, so pushing those bits HIGH turns them OFF. sei(), GIMSK, and PCMSK0, if I remember the datasheet correctly (doubtful), get interrupts working. The debounce variables probably could be set elsewhere but here they shall remain for now.
Main Program: Slow Loop
if (timer2Counter >= timer2Overflow) { }
I'm covering the main program in sections, starting from the inside out. The timer2 loop runs at 1 kHz.
exGroundStatePrevious = exGroundState; exGroundState = 0; if (((inputStatus & 0b00100000) > 0) & (exDebounceCount1 == debounceValue)) { exGroundState += inputMagnitude; } if (((inputStatus & 0b00001000) > 0) & (exDebounceCount2 == debounceValue)) { exGroundState += inputMagnitude; } if (((inputStatus & 0b00000010) > 0) & (exDebounceCount3 == debounceValue)) { exGroundState += inputMagnitude; } if (((inputStatus & 0b00000001) > 0) & (exDebounceCount4 == debounceValue)) { exGroundState += inputMagnitude; } if (((inputStatus & 0b00010000) > 0) & (exDebounceCount5 == debounceValue)) { exGroundState += inputMagnitude; } inGroundStatePrevious = inGroundState; inGroundState = 0; if (((inputStatus & 0b00000100) > 0) & (inDebounceCount1 == debounceValue)) { inGroundState -= inputMagnitude; }
This is going to sound horrible, but sometimes I like writing repetitive code. As in, man... I just figured something out and I need to do it six times, time to copy-paste and change a few characters! Makes it look like I got a lot done [shudder].
I start by storing the current excitatory or inhibitory membrane potential value in the appropriate 'previous' variable. Remember--I know what inputStatus is, I get it as soon as anything changes via the interrupt service routine. Each of those IF statements just masks that value against a few bytes (again, spelled out so I understand 'em) to see when various inputs are high. If they're high, and their debounce counters are full, I modify the appropriate variable based on the inputMagnitude value.
Oh man, I just remembered why I did it this way, and why they're called 'ground state'. This is the logic that allows me to use Exciters--you know, the shorting jumpers that allow me to hold a Neuron at a given potential value. Essentially, I can 'sensitize' Neurons using an Exciter so their new ground state is 70 instead of 0, meaning they'll hit an action potential with a single excitatory pulse. Okay, I should probably revise this post down the road to make it more clear--if you're reading this, I apologize for not understanding my own code and documentation.
Also just realized that I never reset the debounce counters, so... uh... they always stay full. Hmm, I guess they aren't as necessary as I thought they might be? Next section!
if (exGroundState < exGroundStatePrevious) { decayPotential += exGroundStatePrevious - exGroundState; } if (inGroundState > inGroundStatePrevious) { decayPotential -= inGroundState - inGroundStatePrevious;
Looks to see if excitatory or inhibitory inputs have been REMOVED--as in, exGroundState gets SMALLER or inGroundState gets BIGGER. If either happens, we toss the difference into the decayPotential variable so it can start fading.if (potentialTimerCounter >= potentialTimerOverflow) { decayPotential = (decayPotential * 95) / 100; }
Fading using integer math to multiply by 0.95 every clock cycle. Pretty basic; once it gets low enough it rounds to 0. I think? Hmm, now the spreadsheet is telling me that it might stop at 10. I should look in to that, I suppose. It seems to be working in hardware.if (exDebounceCount1 < debounceValue) { exDebounceCount1++; } if (exDebounceCount2 < debounceValue) { exDebounceCount2++; } if (exDebounceCount3 < debounceValue) { exDebounceCount3++; } if (exDebounceCount4 < debounceValue) { exDebounceCount4++; } if (exDebounceCount5 < debounceValue) { exDebounceCount5++; } if (inDebounceCount1 < debounceValue) { inDebounceCount1++; }
If I'm not mistaken, all of this code is pretty much useless--I never reset the debounce counters so none of these statements should ever resolve true. Hmmph. Something to play around with.if (fireTimerCounter < fireTimerOverflow) { fireTimerCounter++; } if (fireDelayCounter < fireDelayOverflow) { fireDelayCounter++; }
Fire timer stuff, relevant later on. Not much to say now.potentialTimerCounter++; timer2Counter = 0;//reset SLOW loop
Iterate timers and reset the loop!Main Program: Fast Loop
Okay, so I think I've made the assumption for a long time that this stuff happens really fast because it's inside this:
if (TCNT1 >= timer1Overflow) { }
TCNT1 is the main timer, currently set to the AVR clock rate. BUT HERE'S THE THING--if timer1Overflow is only 10, and I've got more than 10 lines of code (or 10 clock cycles, which could probably be 1 line of crappy code) between the brackets, it will SLOW DOWN to the rate of program execution! I think that's why I've gotten thrown off by timing crap--my loop speed is getting stretched by a bunch of code. Which is shown in this section.potentialTotal = decayPotential + inGroundState + exGroundState; if (potentialTotal >= 100) { fireTimerCounter = 0; decayPotential -= inputMagnitude * 4; }
We sum potentialTotal a lot, as it's in the fast loop. Also, this includes firing logic--if the total potential exceeds 100, firing happens and the decay plummets like crazy (to -280 with the current inputMagnitude value). I guess that's why changing the inputMagnitude value will affect sensitivity but NOT refresh rate. More on that later.if ((potentialTotal == 0) & (fireTimerCounter == fireTimerOverflow)) { ledRedfade = 0; ledGreenfade = 100; ledBluefade = 0; } if ((potentialTotal > 0) & (fireTimerCounter == fireTimerOverflow)) { ledRedfade = potentialTotal; ledGreenfade = 100 - potentialTotal; ledBluefade = 0; } if ((potentialTotal < 0) & (potentialTotal >= -100) & (fireTimerCounter == fireTimerOverflow)) { ledRedfade = 0; ledGreenfade = 100 - (-potentialTotal); ledBluefade = -potentialTotal; } if ((potentialTotal < -100) & (fireTimerCounter == fireTimerOverflow)){ ledRedfade = 0; ledGreenfade = 0; ledBluefade = 100; } if (fireTimerCounter < fireTimerOverflow) { ledRedfade = 800; ledGreenfade = 800; ledBluefade = 800; fireDelayCounter = 0; }
Remember how I said that Neuron LED colors fade in a non-linear fashion? Yup, this covers that logic. Green at 0, fades to Red approaching the action potential, fades to Blue during the refractory period, stays Blue when it's REALLY far into the refractory period, and fires like crazy when the fireTimerCounter drops.Okay, this is a little trick. An earlier iteration was too bright--everything was indexed to full LED brightness. When I bumped the clock frequency up to 8 MHz from 1 MHz, I didn't change the 0-100 scale of LED brightness (or anything else), but I DID change the slow loop update frequency--as such, most of the time the LEDs run on a 12.5% duty cycle and no longer hurt your eyes when you're staring at a table full of them. However, I wanted flashes to be bright--now they stand out a lot.
if ((fireDelayCounter < fireDelayOverflow) & (fireDelayCounter > fireDelayOverflow / 2)) { PORTA |= (1<<6); } if (fireDelayCounter == fireDelayOverflow) { PORTA &= ~(1<<6); }
What happens when a Neuron fires? BAM! ACTION POTENTIAL! SEND A SIGNAL DOWN THE AXON! AKA, flip the second most significant bit of PORTA after a suitable delay.updateLEDs(timer2Counter, ledRedfade, ledGreenfade, ledBluefade); timer2Counter++; //increment SLOW loop TCNT1 = 0; //reset FAST loop
Run the LED update function (it runs a lot!), increment the slow loop counter, and reset the fast counter.IF YOU MADE IT THIS FAR:
I'm sorry, you've been on quite a journey. I couldn't sleep--for some reason, I had to drag myself out of bed to read through and document some code that I haven't take a critical look at in some time. This a great demonstration of the futility of documentation--even reading through my comments, it took me some time to grasp a few basic concepts about how the program operates, such as the ground potential functions.
Again--constructive criticism is encouraged. I've figured a few things out tonight:
- I need to combine things into functions more (duh)
- It doesn't look like I ever fully implemented the debounce routine
- I'm probably clogging up the fast loop, hence it running super duper slow style
- Documentation is always worthy of improvement
More to come--next time featuring videos of blinky Neurons!
-
Neuron v0.4 quick overview
12/13/2014 at 14:45 • 0 comments -
Planning for v0.5
12/21/2014 at 04:47 • 0 commentsNeuron v0.4 has been fantastic; the platform more than meets my expectations. The board has not developed any electrical issues, and the hardware design does not seem to constrain progress. The steep learning curve of AVR-C (and embedded programming in general) has taken up most of my attention, with eight-board build-outs providing a much-needed break between coding sessions. With that said, I've tried to keep track of a few gripes, roughly outlined here.
- The LED isn't great at being "RGB". Specifically, the red wavelength is about 20-30 nm or so too short; it's sort of an orange-red. During normal operation, the LED won't be seen with only its red element on, since (at least with the current firmware) that would occur very close to an action potential. However, the 70% level is a pretty common sight, since it's the point a single Exciter will hold; with a better RGB element, this might be more of a pure orange. If I can find something for <$0.25 each that fits this criteria, I think it's worth a shot.
- Bigger pads. Everywhere. The current board design has enough room between components that I can at least stretch the standard footprints out a bit to improve reworkability. Pulling the dropping resistors away from the LED a bit might be necessary.
- More on-board axon connections! Maybe a dedicated axon with a built-in terminal that ends in wired plugs rather than header--this would be fairly easy to construct with a bit of heat shrink to connect a bundle of standard axon halves. Or just 2-plug, 4-plug, and 6-plug axons, with the 4- and 6- units having one longer lead to connect to the upstream Neuron.
- Cheaper. Always cheaper, if I can swing it. That means looking at the most expensive bits--the circuit board, then the microcontroller, then the LED, then a lot of space before the passives and connectors.
- Improved programming interface. I think a commercially available PCB-based solution might serve me best--the cheapest option at scale since it just requires a bit of drilling and de-masking, and fast for programming lots of units in series.
- More flexibility on the dendrite side. I've thought about this most of all, even though it's not the highest priority right now since I rarely, even with 30+ Neurons, fill all six Dendrite headers on a single board. Here's the thing--I think I'm mostly constrained by item (3) on this list right now. My Axon Terminal design isn't fantastic--broken perf board bits with heat shrink and a few headers, meaning each one requires three additional Axons to function completely. But if I fix this problem, I'll start using tons of 4-plug and 6-plug axons in my designs, and the Dendrite constraint is really tough--since I take up an entire I/O line for each Dendrite, I'll need to use a different (or multiple) chips to gain I/O. Or cascade branches of Neurons, adding potentially unwanted delays to a loop. Or building dedicated 'high volume' Neurons, which would double the firmware sets (even if they're only slightly different) I'd need to maintain, and increase the BOM length and the number of circuit board designs...
So I started mulling it over and think I could drastically change the electrical design of the Dendrite system. Rather than looking for incoming voltage pulses on an upstream Neuron, I could build some kind of a circuit that utilizes the onboard ADC to figure out how many simultaneous signals are getting to a big parallel bus.
More to come!
-
More thoughts on v0.5
12/21/2014 at 22:28 • 8 commentsWARNING: This is a long post related to future planning and likely will not be acted on for some time. Most of the ideas below haven't been thoroughly thought through (wowsers), so read at your own risk.
I haven't abandoned v0.4; I'm roughly 60% through the production run and as I covered in the previous post, no game-ending issues have popped up. I'm going to keep using the current iteration until... well, who knows? Until its constraints get too frustrating. More likely than not, I won't consider actively developing a new iteration until ~120 Neurons is no longer enough to hold my interest. Having said that, I couldn't sleep last night and did a bit of 1:00 AM whiteboard brainstorming which I'll decipher in this log update.
I'm going to go through the ideas here (I had enough presence of mind to number them chronologically). This post will serve as a reminder, more than anything--future Zach, make sure you think about this stuff before ordering the next generation of PCBs. Apologies, as always, for the poor quality of the whiteboard pictures...
- New PCB concept drawing
- ATtiny13A--the cheapest of the ATtiny series, and surprisingly it doesn't seem to be cheaper than the 44A in similar quantities. In any case--the idea is to back the I/O count down as much as possible. I suppose as pictured, I'd still need 8 I/O lines--three Dendrites (including the Learn Mode connector), two Axon options, and the RGB LED. Maybe the 44A is still the right call.
- Big deal here--each dendrite type has one connector rather than many. I'll get in to more details later, but this design includes some type of external splitter that allows multiple signals to feed a single dendrite.
- More on 'learn mode' later, too.
- The inhibitory axon is lower priority--that would complicate a lot of things but might prove interesting. Idea is--plug an Inhibitory Axon into an Excitatory Dendrite and it--does what? TBD, I suppose.
- Notes on the dendrite system
- So... the new dendrites will use the ATtiny platform's built-in 10-bit analog-to-digital capability. That means they'll be looking at voltage inputs between 0 and 5vdc.
- The analog front-end--that's the detail I'm conveniently skipping over here. This part of the system will convert simultaneous dendritic excitations into a proportional voltage response using some as-of-yet nonexistent circuit. One complicating factor--I still want exciters to work!
- Options for excitatory and inhibitory dendrites
- See drawing (1) on the right? Yup, this relates to the two dendrites on v0.5.
- Here's the idea--I want to be able to plug a single unbranched (/simple) axon into either of these dendrites and have it work, but I also want to be able to split the dendrite. Maybe call the split version a 'soma', since that is the cell wall that dendrites branch out from?
- Drawing conventions
- Lest anybody gets confused, these are the 'schematic symbols' I'm using tonight. To be clear--plugs live on the ends of wires, while headers are soldered to PCBs.
- Dendrite expander idea
- This part could connect to the inhibitory and excitatory dendrite headers on the board. See? 1-to-5! Maybe I could make a few different standard split ratios--1:3, 1:5, 1:8, etc?
- One key idea here--separate the splitter board from the wire/plug. Not drawn but indicated with an arrow--splice a plug onto both ends of the wire, then put an input header on the board? Might bring down overall mfr costs and make everything a bit more modular?
- Thinking about synapses and weighting
- Linked via twisty arrow to idea (2).
- More far-out ideas here--making the axon-dendrite interface (synapse) something other than a 'perfect' conductor.
- If 'weighting' can be done using resistance--maybe use CdS cells as passive weighting components? I suppose cadmium doesn't go with RoHS, huh? Would the LEDs from other Neurons throw this off?
- Ideally--do 'weighting' in software (learning mode) AND hardware. How?
- v0.5 dendrite circuit (see below)
- v0.5 axon terminal circuit (see below)
- v0.5 axon (board level) circuit
- Pretty basic block diagram of a potential inter-Neuron circuit.
- Circuit "A", in the Neuron dendrite system, would convert the number of simultaneous inputs (either signals or exciters) into a proportional voltage, as shown in the graph on the lower right.
- Circuit "C", in the Neuron axon system, would allow each Neuron to add to the total voltage produced by "A" when its Neuron fires.
- Circuit "B" would allow multiple Neurons to send signals to a single downstream Neuron. What to call this? 'Soma'?
- Dendrite clusters and axon terminals
- Basic terminology--Dendrite Clusters are the input splitters shown in idea (5), while Axon Terminals are standard axons pre-soldered in parallel.
- More on dendrite clusters
- Yup, just added on to idea (5) here. Not much beyond the headers being in parallel with passive components as necessary (no microcontroller!). I want these to be scalable as needed!
- More on axon terminals
- I described this under idea (10)--just illustrated here. Ideally, everything is passive and in parallel like it is today!
- Do I need both Axon Terminals AND Dendrite Clusters? What about a 'splitter' and an extending Axon?
- Overall goals for v0.5--big picture
- Every Neuron version has been cheaper than the previous. Well, except v0.1. In any case, I don't want to break that cycle--as such, recreating one of the v0.4 units should not be more than ~$3.50 or so.
- In ideas (7), (8), and (9) I showed a proposed block diagram of the new interconnection system. If I can make circuit "B" in (8) unnecessary, then the "dendrite clusters" and "axon terminals" will just be parallel circuits--that makes manufacturing really simple and cheap and (hopefully) scalable.
- Cheap passives--circuits "A" and "C" are additions to the v0.4 design! Gotta make 'em as cheap as possible! That means no extra microcontrollers!
- More flexibility with connections--duh. That's the whole point. Some Neurons only have one dendrite. Some have TONS of dendrites. I need both options!
- The bonus would just be cool. Some kind of modular circuit that would change the weighting of a given input (or inputs). That gets closer to emulating real-world synapses--as in, not every connection is made equal.
- Can they learn?
- You can't tell in this image (refer to the master whiteboard picture at the beginning of this log update), but this idea is waaaay over on the other side of the board.
- Learn Mode signal--the best comparison I can make is the HART protocol, since it overlays a digital signal over an analog signal. Same idea here--dendrites and axons behave as they did previously, but they can also send a coded message that downstream Neurons will recognize to switch modes.
- Don't forget to remove blue painter's tape
- This happened when I taped a piece of paper to my whiteboard a few months ago. Normally I just avoid the area, but I needed the whole sheet for this brain dump--as such, it's marked as the Whiteboard Damage Zone.
- Dendrite waveform
- Here is what you might see if you snoop a dendrite with a 'scope. Note that the voltage is quantized to a degree, allowing us to differentiate between the number of inputs sending active signals (exciters AND action potentials!).
- Learn mode signal
- Extended from the previous image--the 'fast tone' just needs to be unique. As in, something that wouldn't be recreated by normal Neuron activity--maybe ten state changes in a certain number of milliseconds or something.
- How many modes? Maybe two--Learn and Run. Two different tones for different modes, or a toggling set up?
- Learn mode signal networking
- Should Learn Mode (and Run Mode) signal propagation follow the standard network? As in, if a Neuron is placed in Learn Mode, all downstream Neurons are placed in the same mode?
- Seems like electrically, the Learn Mode signal should propagate as we want it to without any special software considerations--all downstream Neurons would get the signals, but since Axons don't listen any lateral Neurons wouldn't get the message.
- What happens during Learn Mode? Maybe it's identical to Run Mode, but input weighting changes based on action potential frequency? How can we adjust input weighting when dendrites are in parallel?
- Learn mode propagation diagram
- A bit blurry, oops. Black squares are Neurons, blue lines are standard Axon-->Dendrite connections, and green lines are Learn Mode signal propagation.
- New peripheral--the Learning Remote! Used to inject Learn Mode signals into a given Neuron.
- Learn mode features
- Also blurry--sorry.
- Describes what happens in Learn Mode--Neurons behave normally but would start increasing input weights.
- Again--how do we differentiate between individual Dendrite connections? Would this setup only work with unique inputs (as with v0.4)?
- Learn Mode Jumpers--connect standard signals to the Learn Mode input (see idea (1)) and ONLY Learn Mode signals will be 'heard'. Allows Learn Mode to propagate to non-connected network sections.
- Local/regional learning!
- This picture got a bit stretched and is super blurry. Sorry.
- This connects to the diagram in idea (19)--it just shows linking Learn Mode jumpers to a normally unconnected neural network.
- Seems like a 'bonus feature'.
Okay--back to v0.4 soon, I promise. With any luck, I'll reference these ideas when I take the next steps in v0.5 development. I think the analog input concept could improve network flexibility--it would be nice to have 10+ dendrite Neurons without specialized boards or programs. But for now, that's a solution lacking a problem.
Zach
- New PCB concept drawing
-
22-Neuron v0.4 Test
12/26/2014 at 03:29 • 0 commentsI have a bunch more Neurons, but I unexpectedly ran out of Axons; I crimped up a few more and remembered how long they take to manufacture, so I got lazy and stopped at 22 elements for this test.
This video is pretty straightforward (and quite short!); I arranged 22 Neurons into a loop, making a few modifications as I went:
- All Neurons are equipped with Exciters; as such, they are deep yellow (indicating the current membrane potential level of 70%).
- I numbered the Neurons counter-clockwise starting with the first one to pulse (triggered by the snap action switch). Neuron #5 is split using an Axon Terminal; part of its output recycles to an excitatory dendrite of Neuron #1. This makes the loop self-sustaining, sending periodic pulses down the chain to Neurons #6 through #22.
- Neuron #22 sends its pulses to the inhibitory dendrite of Neuron #3; this is timed such that the pulse arrives right before Neuron #2's excitatory pulse, effectively 'quenching' the loop.
- I hooked my ammeter up to the power cord's current measurement loop; you can see the current spikes caused by each excitation, since the LED brightness goes from 12.5% to 100%. Resting current draw is ~6.5 mA per Neuron--not bad!
And so: click the switch, get four pulses! Well, five pulses. Pulse #5 gets shot down by pulse #1.
Blinky.
-
This Project: Very Much Still Alive.
05/12/2015 at 19:08 • 0 commentsI glanced through my project logs and realized that I haven't posted much about this project in some time. That is lame.
You know what is even more lame? @NeuroJoe and I have been working on it like crazy. For example, I managed to go 12 for 12 in Neuron v04 manufacturing the other day:
(side note: yup, they draw a lot of current at full brightness. This is just a test program that double-checks LED wiring.)
So. I don't have much else to say here and now, but I'm committing to a comprehensive project update by the end of the week. Or weekend. Or something like that. NEAR FUTURE, okay?
So stay tuned, eh?
-z
-
NeuroTinker, Grants, Progress, Excitement, Etc.
08/13/2015 at 00:08 • 0 commentsRadio silence on Neurons throughout most of summer. I still owe this project page a major update. Rather than wasting [too much] time with excuses, let's get started bringing everyone who may be interested up to speed.
That's us. NeuroTinker, LLC. Our site is a bit sparse right now, but we're slowly building up content and getting background information filled in. We hired my excellent cousin Lauren Everett to design our logo and put together a basic website framework; she did an excellent job (as you can see) and was terrific to work with.
So what's the plan? We want to develop an educational platform that gets people into neuroscience. We want it to be modular, economical, scientifically accurate, fun, open-source, and accessible to a broad range of educational achievement levels. While chemistry students pick up their ball-and-stick model kits from the campus bookstore, aspiring neuroscientists will get NeuroBytes.
How do we do that? We get NeuroBytes into the hands of lots of students as quickly as possible. We figure out how to use the platform to model real parts of the nervous system. We add new modules and sensors and outputs and try to build something exciting and engaging. We iterate a lot. I (by necessity) learn a lot more about microcontroller programming. We talk to educators and figure out what might improve the classroom experience.
As of today, we've heard back from a few dozen educators across a wide range of institutions who all seem quite stoked about the concept. We have applied for two SBIR Phase I grants focusing on different specific areas of educational technology (but we probably won't hear back for a few months). We sold six NeuroBytes v04 prototypes for integration into a Crazy Project (Crazy Project owner, feel free to comment if you wish). And we built more NeuroBytes:
and worked on some new NeuroBytes interfaces:
I'm hoping to have a firmware update pushed out in the next week or two; this revision will include the servo driver test code shown above along with a to-be-developed Motor NeuroBytes module setup.
Woo!
-
Patellar Reflex Model
08/13/2015 at 04:14 • 0 commentsOkay, quick update. I added a linear decay function to the Motor NeuroBytes module (the servo output) and cut a little leg model out of matteboard:
It's quite simplified as it doesn't illustrate the inhibitory portion of this reflex, but the model does make the whole project seem a bit more real.
-
Patellar reflex model, part 2
08/19/2015 at 03:55 • 0 commentsI putzed about with the Motor NeuroBytes firmware a bit tonight:
This program is called v04run_servo-ex-inh in the Github repo. In the video, I've attached two NeuroBytes in series in such a way that one excites the next while the first excites the Motor NeuroBytes module and the second inhibits it. A few notes:
- Inhibiting or exciting the Motor NeuroBytes immediately moves it to 100% or 0% from its normal resting position of 50%. I'm guessing that each inhibition or excitation should actually move the current state by x amount, kinda like the current standard NeuroBytes firmware just shifts the immediate resting point of the board by 70%. In other words, exciting or inhibiting the Motor NeuroBytes board should produce a relative rather than an absolute change.
- Standard NeuroBytes insert a delay between the LED pulse and the axon output, which makes the flashes out of phase with the Motor NeuroBytes module movement. Might make sense to move the delay to the input side--as in, one hits the button and the NeuroBytes module doesn't instantly react, but when it does it immediately dumps a pulse down its axon.
So. More to come.