Close

Log 1

A project log for ESP32 EEG

Heavily inspired by OpenBCI, especially their ganglion board design, but with an ESP32 handling communication/control

PrestonPreston 03/03/2021 at 01:090 Comments

I have the first revision of my PCB design fabricated and I've populated enough of the board to read from 1 channel. A 1000 sample recording is shown below:

I'm not sure I have the conversion correct, but ~10-20 microvolts of input referred noise seems reasonable.

I'm currently running a build of micropython with ulab on the esp32, and that's been really useful for debugging communication. The code I ran to acquire the above data is below. I'll probably try to record some actual biopotentials (EMG/ECG before sticking it to my head), and then I'll start debugging the impedance measurement circuit. I'll probably start out using the Ultracortex Mark III headset design from openbci, but ultimately I want to explore other headset designs.

from machine import SPI,Pin

DEV_ADD = 0x40
MCP_READ = 0x01
MCP_WRITE = 0x00

STATUSCOM = 0x18
CHAN_0 = 0x00
CHAN_1 = 0x02
CHAN_2 = 0x04
CHAN_3 = 0x06
GAIN = 0x16
CON0 = 0x1A
CON1 = 0x1C

r_gain=bytearray(1)
w_gain=bytearray(1)
r_statcom=bytearray(1)
w_statcom=bytearray(1)
r_con0=bytearray(1)
w_con0=bytearray(1)
r_con1=bytearray(1)
w_con1=bytearray(1)
r_0=bytearray(1)
r_1=bytearray(1)
r_2=bytearray(1)
r_3=bytearray(1)

r_gain[0]= DEV_ADD | GAIN | MCP_READ
w_gain[0]= DEV_ADD | GAIN | MCP_WRITE
r_statcom[0]=DEV_ADD | STATUSCOM | MCP_READ
w_statcom[0]=DEV_ADD | STATUSCOM | MCP_WRITE
r_con0[0]= DEV_ADD | CON0 | MCP_READ
w_con0[0]= DEV_ADD | CON0 | MCP_WRITE
r_con1[0]= DEV_ADD | CON1 | MCP_READ
w_con1[0]= DEV_ADD | CON1 | MCP_WRITE
r_0[0]=DEV_ADD | CHAN_0 | MCP_READ
r_1[0]=DEV_ADD | CHAN_1 | MCP_READ
r_2[0]=DEV_ADD | CHAN_2 | MCP_READ
r_3[0]=DEV_ADD | CHAN_3 | MCP_READ


MCP_SPI=SPI(1, 10000000, sck=Pin(14), mosi=Pin(13), miso=Pin(12))
MCP_SPI.init()

MCP_SS=Pin(27,Pin.OUT)

MCP_DRDY=Pin(26,Pin.IN)
DRDY=False
def callback(p):
 global DRDY
 DRDY=True

MCP_DRDY.irq(trigger=Pin.IRQ_FALLING, handler=callback)


statcom = 0xB9000F
config0 = 0x3C0050
config1 = 0x0F0000 #channels off
config1 = 0x000000 #channels on


#read 24-bit value
MCP_SS.value(0)
MCP_SPI.write(r_3) #register address you want to read from
MCP_SPI.read(3)
MCP_SS.value(1)

#write 24-bit value
MCP_SS.value(0)
MCP_SPI.write(w_statcom) #register address you want to write to
MCP_SPI.write(b'\xB9') #data to write MSB
MCP_SPI.write(b'\x00') #data to write
MCP_SPI.write(b'\x0F') #data to write
MCP_SS.value(1)


#read some number of samples to a data array
data=bytearray(3000)
tmp=bytearray(3)
i=1
point=0
while i<1001:
 if DRDY:
  MCP_SS.value(0)
  MCP_SPI.write(r_3)
  MCP_SPI.readinto(tmp)
  MCP_SS.value(1)
  data[point:point+3]=tmp
  i+=1
  point=(i-1)*3
  DRDY=0

#save the data to a file on the ESP32
f=open('data.txt')
f=open('data.txt','w')
f.write(data)
f.close()

Discussions