Skip to content

Commit 24490d5

Browse files
first commit
0 parents  commit 24490d5

File tree

7 files changed

+397
-0
lines changed

7 files changed

+397
-0
lines changed

examples/analogIn/analogIn.ino

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* An example where a single neuron is driven by analog input (acting like the
3+
* pre-synaptic current coming into the neuron's axon.
4+
*/
5+
6+
7+
#include <Neurons.h>
8+
9+
int neuronOutputPin = 9;
10+
int neuronInputPin = A1;
11+
Neuron testNeuron(neuronInputPin, neuronOutputPin);
12+
13+
void setup(){
14+
pinMode(testNeuron.outputPin,OUTPUT);
15+
pinMode(testNeuron.inputPin, INPUT);
16+
Serial.begin(9600);
17+
}
18+
19+
void loop(){
20+
21+
testNeuron.inputCurrent = analogRead(testNeuron.inputPin)/3;
22+
23+
testNeuron.calculateMembranePotential((float)testNeuron.dt);
24+
testNeuron.LED_Output(testNeuron.outputPin);
25+
delay(testNeuron.dt);
26+
}

keywords.txt

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#######################################
2+
# Datatypes (KEYWORD1)
3+
#######################################
4+
5+
Neuron KEYWORD1
6+
Network KEYWORD1
7+
8+
#######################################
9+
# Methods and Functions (KEYWORD2)
10+
#######################################
11+
12+
C KEYWORD2
13+
gL KEYWORD2
14+
EL KEYWORD2
15+
VT KEYWORD2
16+
Vspike KEYWORD2
17+
spike KEYWORD2
18+
inputPin KEYWORD2
19+
outputPin KEYWORD2
20+
inputCurrent KEYWORD2
21+
setInputPin KEYWORD2
22+
setOutputPin KEYWORD2
23+
calculateMembranePotential KEYWORD2
24+
LED_Output KEYWORD2
25+
26+
connectivityMatrix KEYWORD2
27+
neuronCount KEYWORD2
28+
sensoryNeuronCount KEYWORD2
29+
sensoryNeurons KEYWORD2
30+
defaultOutPins KEYWORD2
31+
defaultInputPins KEYWORD2
32+
times KEYWORD2
33+
setConnectivityMatrix KEYWORD2
34+
Neurons KEYWORD2
35+
setSensoryNeurons KEYWORD2
36+
issueSpikes KEYWORD2
37+
updateNeurons KEYWORD2
38+
Visualize KEYWORD2

library.properties

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name=Neurons
2+
version=1.0.0
3+
author=Rishabh Malviya
4+
maintainer=Rishabh Malviya <rishabh.malviya@gmail.com>
5+
sentence=Implements LIF neurons in Arduino by simulating membrane potentials and currents in code.
6+
paragraph=Implements LIF neurons in Arduino by simulating membrane potentials and currents in code. It is inspired by the Spikeee.h library, but will soon also have STDP learning and other Neuron models implemented in it. A Neuron and Network class can together be used to make any small neuronal motif in Arduino.
7+
category=Device Control
8+
url=
9+
architectures=avr

src/Network.cpp

+143
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
/*
2+
Network.cpp - Library for network of LIF neurons in Arduino.
3+
Created by Rishabh Malviya, October 17, 2015.
4+
Released into the public domain.
5+
*/
6+
7+
#include "Network.h"
8+
9+
#define MAX_NEURONS 6
10+
11+
const int Network::defaultOutPins[MAX_NEURONS] = {7, 4, 2, 1, 0, 6};
12+
const int Network::defaultInputPins[MAX_NEURONS] = {A0, A1, A2, A3, A4, A5};
13+
int Network::dt;
14+
/*CONSTRUCTORS*/
15+
16+
//Default Constructor
17+
Network::Network(int numberOfNeurons){
18+
//Sanity check
19+
if(numberOfNeurons>MAX_NEURONS) exit;
20+
21+
//Set neuronCount
22+
neuronCount = numberOfNeurons;
23+
24+
//Initialize Neurons with default output pins
25+
for(int i=0; i<numberOfNeurons; i++){
26+
Neurons[i].setOutputPin(defaultOutPins[i]);
27+
pinMode(defaultOutPins[i],OUTPUT);
28+
}
29+
30+
//Re-configure everything to pinChangeInterrupts
31+
cli(); //disable interrupts during interrupt configuration
32+
33+
EIFR |= 0b00000011; //Clearing externalInterrupt flags.
34+
EIMSK &= 0b11111100; //Disabling externalInterrupts
35+
36+
PCIFR |= 0b00000111; //Clearing pinChangeInterrupt flags
37+
PCICR &= 0b11111000; //Disabling all pinChangeInterrupts
38+
39+
sei();
40+
41+
};
42+
43+
44+
//Constructor with connectivity matrix
45+
Network::Network(int numberOfNeurons, int connectivity[]){
46+
//Sanity check
47+
if(numberOfNeurons > MAX_NEURONS) exit;
48+
if((sizeof(connectivity)/sizeof(connectivity[0])) != (numberOfNeurons*numberOfNeurons)) exit;
49+
50+
//Initialize Variables
51+
neuronCount = numberOfNeurons;
52+
53+
//Initialize Neurons with default output pins
54+
for(int i=0; i<numberOfNeurons; i++){
55+
Neurons[i].setOutputPin(defaultOutPins[i]);
56+
pinMode(defaultOutPins[i],OUTPUT);
57+
}
58+
59+
//Re-configure everything to pinChangeInterrupts
60+
cli(); //disable interrupts during interrupt configuration
61+
62+
EIFR |= 0b00000011; //Clearing externalInterrupt flags.
63+
EIMSK &= 0b11111100; //Disabling externalInterrupts
64+
65+
PCIFR |= 0b00000111; //Clearing pinChangeInterrupt flags
66+
PCICR &= 0b11111000; //Disabling all pinChangeInterrupts
67+
68+
sei();
69+
70+
//Set Connectivity Matrix
71+
setConnectivityMatrix(connectivity);
72+
73+
};
74+
75+
76+
77+
/*PRIVATE MEMBER FUNCTIONS*/
78+
79+
void Network::setConnectivityMatrix(int connectivity[]){
80+
for(int i=0; i<neuronCount; i++){
81+
for(int j=0; j<neuronCount; j++){
82+
connectivityMatrix[i][j] = connectivity[i*neuronCount + j];
83+
}
84+
}
85+
};
86+
87+
88+
89+
/* PUBLIC MEMBER FUNCTIONS */
90+
91+
void Network::setSensoryNeurons(int* sensoryNeuronIDs, int sensoryNeuronCount_){
92+
//Sanity check
93+
if(sensoryNeuronCount_>neuronCount) exit;
94+
95+
//Set sensoryNeuronCount
96+
sensoryNeuronCount = sensoryNeuronCount_;
97+
98+
//Enable interrupts for sensory neurons
99+
bitClear(PCICR,1);
100+
for(int i=0; i<sensoryNeuronCount; i++){
101+
bitSet(PCMSK1,sensoryNeuronIDs[i]);
102+
pinMode(defaultInputPins[sensoryNeuronIDs[i]],INPUT);
103+
digitalWrite(defaultInputPins[sensoryNeuronIDs[i]],HIGH); //Stabilising through internal pull-up resistor
104+
}
105+
bitSet(PCICR,1);
106+
};
107+
108+
void Network::updateNeurons(){
109+
static int presentTime = micros();
110+
111+
for(int i=0; i<neuronCount; i++){
112+
presentTime = micros();
113+
Neurons[i].calculateMembranePotential(dt);//((float)((presentTime-initTimes[i])/1000));
114+
//Serial.println((float)((presentTime-initTimes[i])/1000));
115+
//Serial.println(Neurons[i].membranePotential); Serial.println();
116+
//times[i] = presentTime;
117+
}
118+
119+
};
120+
121+
void Network::issueSpikes(){
122+
for(int neuronID=0; neuronID<neuronCount; neuronID++){
123+
if(Neurons[neuronID].spike){
124+
for(int i=0; i<neuronCount; i++){
125+
Neurons[i].inputCurrent += (connectivityMatrix[neuronID][i])*200;
126+
}
127+
}
128+
}
129+
};
130+
131+
void Network::Visualize(){
132+
for(int neuronID=0; neuronID<neuronCount; neuronID++){
133+
Neurons[neuronID].LED_Output(defaultOutPins[neuronID]);
134+
}
135+
};
136+
137+
138+
/* DESTRUCTORS */
139+
140+
//Default Destructor
141+
Network::~Network(){
142+
143+
}

src/Network.h

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#ifndef Network_h
2+
#define Network_h
3+
4+
#include "Arduino.h"
5+
#include "Neurons.h"
6+
7+
#define MAX_NEURONS 6
8+
9+
class Network{
10+
private:
11+
bool sensoryNeurons[MAX_NEURONS]; //only neurons with inputPins.
12+
void setConnectivityMatrix(int connectivity[]);
13+
14+
public:
15+
Neuron Neurons[MAX_NEURONS];
16+
int neuronCount;
17+
int sensoryNeuronCount;
18+
int connectivityMatrix[MAX_NEURONS][MAX_NEURONS];
19+
static const int defaultOutPins[MAX_NEURONS];// = {7, 4, 2, 1, 0, 6};
20+
static const int defaultInputPins[MAX_NEURONS];// = {A0, A1, A2, A3, A4, A5};
21+
static int dt;
22+
23+
Network(int numberOfNeurons);
24+
Network(int numberOfNeurons, int connectivity[]);
25+
~Network();
26+
27+
void setSensoryNeurons(int* sensoryNeuronIDs, int sensoryNeuronCount_);
28+
void issueSpikes();
29+
void updateNeurons(); //calls 'calculateMembranePotential' for each Neuron
30+
void Visualize();
31+
};
32+
33+
#endif Network_h

src/Neurons.cpp

+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
Neurons.cpp - Library for implementng LIF neurons in Arduino code.
3+
Created by Rishabh Malviya, October 17, 2015.
4+
Released into the public domain.
5+
*/
6+
7+
#include "Neurons.h"
8+
9+
10+
//Default constructor
11+
Neuron::Neuron(){
12+
membranePotential = -60.0;
13+
C = 2000.0;
14+
gL = 5.0/12.0;
15+
EL = -60.0;
16+
VT = 20.0;
17+
Vspike = 60.0;
18+
spike = false;
19+
20+
inputCurrent = 0;
21+
}
22+
23+
//Output Neuron constructor
24+
Neuron::Neuron(int outputPin_){
25+
membranePotential = -60.0;
26+
C = 2000.0;
27+
gL = 5.0/12.0;
28+
EL = -60.0;
29+
VT = 20.0;
30+
Vspike = 60.0;
31+
spike = false;
32+
33+
inputCurrent = 0;
34+
outputPin = outputPin_;
35+
}
36+
37+
//Input and Output Neuron Constructor
38+
Neuron::Neuron(int inputPin_, int outputPin_){
39+
membranePotential = -60.0;
40+
C = 2000.0;
41+
gL = 5.0/12.0;
42+
EL = -60.0;
43+
VT = 20.0;
44+
Vspike = 60.0;
45+
spike = false;
46+
47+
inputCurrent = 0;
48+
inputPin = inputPin_;
49+
outputPin = outputPin_;
50+
}
51+
52+
53+
54+
//Set Input Pin
55+
void Neuron::setInputPin(int inputPin_){
56+
inputPin = inputPin_;
57+
}
58+
59+
//Set Output Pin
60+
void Neuron::setOutputPin(int outputPin_){
61+
outputPin = outputPin_;
62+
}
63+
64+
65+
//Membrane Potential Update Function
66+
void Neuron::calculateMembranePotential(float dt){
67+
float deltaMembranePotential = 0;
68+
69+
if(spike){
70+
membranePotential = VT-40.0;
71+
spike = false;
72+
}
73+
74+
deltaMembranePotential = (inputCurrent - gL*(membranePotential-EL))*(dt/C);
75+
membranePotential += deltaMembranePotential;
76+
77+
if(membranePotential>VT){
78+
membranePotential = Vspike;
79+
spike = true;
80+
}
81+
82+
if(membranePotential<-60.0){
83+
membranePotential = -60.0;
84+
}
85+
86+
inputCurrent = 0;
87+
}
88+
89+
//Visualizing Neuron Output Through LED
90+
void Neuron::LED_Output(int outPin){
91+
boolean output = 0;
92+
93+
if(!spike){
94+
//output = ((membranePotential-EL)*(110/120));
95+
output = 0;
96+
}
97+
else if(spike){
98+
output = 255;
99+
}
100+
101+
digitalWrite(outPin,(int)output);
102+
}
103+
104+
void Neuron::setLeakConstant(float gL_){
105+
gL = gL_;
106+
};
107+
108+
109+
//Destructor
110+
Neuron::~Neuron(){
111+
112+
}

0 commit comments

Comments
 (0)