ArduDreamer

Where did you get the IC's? Can you also post the schematics?

I got the ICs from Texas Instruments (INA126P & TLV2472), Analog Devices (AD5204), and Maxim (DS1307). The passive components and atmega168 I got from digikey. If you want to try building one I would recommend the atmega328 instead, digi was just out of them when I ordered stuff.

The only schematic I have right now is from when I was figuring out the EOG circuit in pspice:

Some things I changed since that schematic: I just power it from FTDI now so I got rid of the 9V battery and 7805. I took out the TLV2472 from the virtual ground circuit and replaced it with an LM358. I reused the TLV2472 to cascade two more 40Hz low pass filters before the final amplification. I replaced the 280ohm resistor in the instrumentation amplifier with a channel on the AD5204. I replaced the 270K resistor on the final amp circuit with a 150K, and I replaced the 10K resistor on the final amp circuit with another channel on the AD5204.

The rest of it I just made as I went on the breadboard so I dont have any schematics right now, but Im going to build a PCB for this and I can post the full schematic after I get it in to eagle

If you would make a shield or PCB, I'm VERY interested in buying one.

Cool. I'm waiting on a couple different types of sleep masks and the reusable electrodes to come in. The adhesive ones I've been using leave nasty red marks next to my eyes after wearing them so my GF has kindly asked my to stop using them =)

:stuck_out_tongue: I think Zeo is selling masks with elektrodes in it.

I just stumbled upon this topic and had to chuckle, since i had a schematic lying around my hard drive for about a year now, looking quite similar. Even used the same InAmp. Had a breadboard version up and running, and began working on a layout for a smd version consisting of three tiny (2x3cm) pcbs connected by flexibel connectors. One board as analog stage with amp and filters, the second with the microcontroller (atmega64) and a third with rs232 and a small rf transceiver module. That way i intended to mount the entire rig directly on the headband, supplied by a small LiPo Battery. Also began looking into the possibility of using active electrodes without the for contact gel, but never came around to do some testing. I had to put the thing on hiatus however, since other things have taken up my time since then.

Thought you might be interested of how others tried something similar. Best of luck to you and your project.

Below my design for the analog stage. I used three electrodes though, with the third directly tied as reference.

Hah cool, I think EOG is the way to go with this type of thing (and it’s just cool).

The Serial C# grapher that got posted inspired me to write an app to go with this. I’ve been using KST in linux to do the graphing, but now I’m going to try writing my own specifically for this, maybe with an integrated dream journal to tie journal entries with the graphs. And it’d be nice to configure everything from an app instead of accessing a menu through minicom.

I got the code somewhat cleaned up. I removed the speaker since it kept waking up my GF. I removed the DS1307 in favor of using a running timer and syncing time on the PC. The PC can give commands to the arduino by sending "#key=value" over the serial connection. The PC gets updates from the arduino at about 375Hz using 115200 baud.

I decided to skip doing a custom app, not worth the work since I got my issues with KST resolved

The autocalibration didn't work all that great, I found it easier to look at the graph and adjust the gains by hand. Would be nice to get it working tho.

Here's the arduino code..

#include 
#include 

#define BAUDRATE 115200

//pins
#define pLED 7
#define pMOSI 11
#define pMISO 12
#define pSCK 13
#define pCS 10
#define pAMP1OUT 2
#define pAMP2OUT 3

//rheostats
#define rAMP1 3
#define rAMP2 1
#define rLED 2

//button interrupts
#define bDELAY 0
#define bTEST 1

struct config_t {
  int ledBrightness;
  int ledOnTime;
  int ledOffTime;
  int delayTime;
  int REMAlarm;
  int EOGREMHi;
  int EOGREMLo;
  int amp1Gain;
  int amp2Gain;
  int REMTime;
  int testTime;
} config;

unsigned long thisMillis = 0;
unsigned long lastMillis = 0;
unsigned long REMStop = 0;
unsigned long testStop = 0;
unsigned long delayStop = 0;
unsigned long startTime = 0;

int ledOn = 0;

char buff[100];

template  int EEPROM_write(int ee, const T& value)
{
    const byte* p = (const byte*)(const void*)&value;
    int i;
    for (i = 0; i < sizeof(value); i++)
        EEPROM.write(ee++, *p++);
    return i;
}

template  int EEPROM_read(int ee, T& value)
{
    byte* p = (byte*)(void*)&value;
    int i;
    for (i = 0; i < sizeof(value); i++)
        *p++ = EEPROM.read(ee++);
    return i;
}

char spi_transfer(volatile char data)
{
  SPDR = data;                    // Start the transmission
  while (!(SPSR & (1< 0)
          config.amp1Gain--;
      } else {
        config.amp1Gain = atoi(value);
      }
      write_pot(rAMP1, config.amp1Gain);
    } else if(!strcmp("amp2Gain", key)) {
      if(!strcmp("u", value)) {
        if(config.amp2Gain < 255)
          config.amp2Gain++;
      } else if(!strcmp("d", value)) {
        if(config.amp2Gain > 0)
          config.amp2Gain--;
      } else {
        config.amp2Gain = atoi(value);
      }
      write_pot(rAMP2, config.amp2Gain);
    } else if(!strcmp("EOGREMHi", key)) {
      if(!strcmp("u", value)) {
        if(config.EOGREMHi < 1024)
          config.EOGREMHi++;
      } else if(!strcmp("d", value)) {
        if(config.EOGREMHi > 0)
          config.EOGREMHi--;
      } else {
        config.EOGREMHi = atoi(value);
      }
    } else if(!strcmp("EOGREMLo", key)) {
      config.EOGREMLo = atoi(value);
    } else if(!strcmp("ledBrightness", key)) {
      config.ledBrightness = atoi(value);
      write_pot(rLED, config.ledBrightness);
    } else if(!strcmp("ledOnTime", key)) {
      config.ledOnTime = atoi(value);
    } else if(!strcmp("ledOffTime", key)) {
      config.ledOffTime = atoi(value);
    } else if(!strcmp("delayTime", key)) {
      config.delayTime = atoi(value);
    } else if(!strcmp("REMAlarm", key)) {
      config.REMAlarm = atoi(value);
    } else if(!strcmp("REMTime", key)) {
      config.REMTime = atoi(value);
    } else if(!strcmp("testTime", key)) {
      config.testTime = atoi(value);
    } else if(!strcmp("startTime", key)) {
      startTime = millis();
    }
    EEPROM_write(0, config);
}
void loop()
{
  if(Serial.available()) {
      doInput();
  } else {
    thisMillis = millis();
    int eog = analogRead(pAMP2OUT);
    if(eog >= config.EOGREMHi || eog <= config.EOGREMLo) {
      if(thisMillis < delayStop) {
          delayStop = config.delayTime;
          delayStop = delayStop * 1000 + thisMillis;
      } else if(!REMStop) {  
        REMStop = config.REMTime;
        REMStop = REMStop * 1000 + thisMillis;
        digitalWrite(pLED, HIGH);
        ledOn = 1;   
        lastMillis = thisMillis;
      } else {
        REMStop = config.REMTime;
        REMStop = REMStop * 1000 + thisMillis;
      }
    }
  if(REMStop && thisMillis > REMStop) {
    REMStop = 0;
    digitalWrite(pLED, LOW);
  }
  if(REMStop || thisMillis < testStop) {
    if(!ledOn) {
      if(thisMillis - lastMillis >= config.ledOffTime) {
        digitalWrite(pLED, HIGH);
        ledOn = 1;
        lastMillis = thisMillis;
      }
    } else {
      if(thisMillis - lastMillis >= config.ledOnTime) {
        digitalWrite(pLED, LOW);
        ledOn = 0;
        lastMillis = thisMillis;
      }
    }
  }    
  if(testStop && thisMillis > testStop) {
    testStop = 0;
    digitalWrite(pLED, LOW);
  }
  //EOG,REM,SLEEPDELAY,AMP1GAIN,AMP1OUT,AMP2GAIN,EOGREMHI,EOGREMLO,REMTIMEOUT
  Serial.print(thisMillis - startTime);
  Serial.print(",");
  Serial.print(eog);
  Serial.print(",");
  if(REMStop) { Serial.print("1024"); } else { Serial.print("0"); }
  Serial.print(",");
  if(delayStop > thisMillis) {
    unsigned long x = config.delayTime;
    Serial.print(map(delayStop - thisMillis, 0, x * 1000, 0, 1024));
  } else {
    Serial.print("0");
  }
  Serial.print(",");
  //Serial.print(map(config.amp1Gain,0,255,0,1024));
  //Serial.print(",");
  //Serial.print(analogRead(pAMP1OUT));
  //Serial.print(",");
  //Serial.print(map(config.amp2Gain,0,255,0,1024));
  //Serial.print(",");
  Serial.print(config.EOGREMHi);
  Serial.print(",");
  Serial.print(config.EOGREMLo);
  Serial.print(",");
  if(thisMillis > REMStop) {
    Serial.print("0");
  } else {
    unsigned long y = config.REMTime;
    Serial.print(map(REMStop - thisMillis, 0, y * 1000, 0, 1024));
  }
  Serial.println();
  
  }  
}

I use this on the PC side to collect the data from arduino and output it to the file KST monitors for graphing. Theres no flow control between the arduino and PC so it does some checks to make sure the data "looks" correct since it sometimes gets messed up if the receive buffer overflows

#include 
#include 
#include 

int main(int argc,char *argv[])
{
        struct timeb tp;
        ftime(&tp);

        FILE * outfile;
        FILE * serial;

        serial = fopen(argv[1], "w+");
        outfile = fopen("dream", "w");

        //sync time on arduino
        fprintf(serial, "#startTime=startTime");

        char data[100];
        char buff[100];

        char *pdata = data;
        char *pbuff = buff;

        int seps = 0;

        unsigned long a_ms;
        int a_eog;
        int a_rem;
        int a_delay;
        int a_eoghi;
        int a_eoglo;
        int a_remt;

        unsigned long pa_ms = 0;

        int go = 0;

        while (1)
        {
                pdata = data;
                pbuff = buff;
                a_ms = 0;
                a_rem = -1;
                a_delay = -1;
                a_eoghi = -1;
                a_eoglo = -1;
                a_remt = -1;
                seps = 0;

                fgets(data, 100, serial);

                //parse string from arduino
                while(*pdata != '\0') {
                        if(*pdata == ',' || *pdata == '\r' || *pdata == '\n') {
                                *pbuff = '\0';
                                if(seps == 0)
                                        a_ms = atoi(buff);
                                else if(seps == 1)
                                        a_eog = atoi(buff);
                                else if(seps == 2)
                                        a_rem = atoi(buff);
                                else if(seps == 3)
                                        a_delay = atoi(buff);
                                else if(seps == 4)
                                        a_eoghi = atoi(buff);
                                else if(seps == 5)
                                        a_eoglo = atoi(buff);
                                else if(seps == 6)
                                        a_remt = atoi(buff);
                                seps++;

                                pbuff = buff;
                                pdata++;
                                continue;
                                if(*pdata == '\r' || *pdata == '\n')
                                        break;
                        } else {
                                *pbuff++ = *pdata++;
                        }
                }

                //do some data sanity checks
                if(seps != 8)
                        continue;
                if(a_ms < 1)
                        continue;
                if(a_eog < 0 || a_eog > 1024)
                        continue;
                if(a_rem != 0 && a_rem != 1024)
                        continue;
                if(a_delay < 0  || a_delay > 1024)
                        continue;
                if(a_eoghi < 512 || a_eoghi > 1024)
                        continue;
                if(a_eoglo < 0 || a_eoglo > 512)
                        continue;
                if(a_remt < 0 || a_remt > 1024)
                        continue;

                //dont log until timer resets on arduino
                if(!go) {
                        if(a_ms > 1000) {
                                printf("%i,%d\n", go, a_ms);
                                continue;
                        } else {
                                printf("%i,%d\n", go, a_ms);
                                go = 1;
                        }
                }

                //use timer from arduino as offset to start time
                int msec = a_ms % 1000;
                a_ms = a_ms/1000 + tp.time;
                if(a_ms > pa_ms + 1) {
                        pa_ms = a_ms;
                        continue;
                }
                msec = msec + tp.millitm;
                if(msec > 999) {
                        msec = msec - 1000;
                        a_ms++;
                }

                //need msec displayed as thousandths with no leading 0
                char fs[10];
                float f = msec;
                sprintf(fs, "%.3f", f/1000);
                char *fp = fs[1];

                //write to log
                fprintf(outfile,"%ld%s,%s",a_ms,fp,data);
        }
        fclose(serial);
        fclose(outfile);
        return 0;
}

KST file for graphing the data (part 1)



  
    1066
    853
    
  
  
  
    DS-dream
    /home/user/dream
    ASCII
    
    
    
    
       P1/XMin        1268324681.1026        P1/XMax        1268325026.1234        P1/YMin        0        P1/YMax        1024        DS-dream/1    DS-dream    /home/user/dream    1    0    -1        DS-dream/1-1    DS-dream    /home/user/dream    1    0    -1        DS-dream/3    DS-dream    /home/user/dream    3    0    -1        DS-dream/4    DS-dream    /home/user/dream    4    0    -1        DS-dream/5    DS-dream    /home/user/dream    5    0    -1        DS-dream/6    DS-dream    /home/user/dream    6    0    -1        DS-dream/7    DS-dream    /home/user/dream    7    0    -1        DS-dream/8    DS-dream    /home/user/dream    8    0    -1        1-1    DS-dream/1    DS-dream/1-1        0        #00aa00        0    0    0    0    0        3    DS-dream/1    DS-dream/3    EOG    0        #009999        0    0    0    0    0        4    DS-dream/1    DS-dream/4        0        #000001    0    0    0    0        1        5    DS-dream/1    DS-dream/5    Delay Timeout    0        #990099        0    0    0    0    0        6    DS-dream/1    DS-dream/6    REM Threshold (R)    0        #ff0000        0    0    0    0    0        7    DS-dream/1    DS-dream/7    REM Threshold (L)    0        #1717c8        0    0    0    0    0  

KST file for graphing the data (part 2). I'll post schematic for the board soon.

  
    8
    DS-dream/1
    DS-dream/8
    REM Timeout
    0
    
    #4f4c51
    
    0
    0
    0
    0
    0
  
  
    
    P1
    
    
    P1
    #000000
    0
    #000000
    #ffffff
    0
    0
    0
    6
    0
    5
    1268324681.1026
    1268325026.1234
    0
    1024
    0
    0
    0
    1024
    
      
      
      0
      1
      DejaVu Sans
      12
    
    
      Column 1
      
      0
      DejaVu Sans
      12
    
    
      
      
      270
      DejaVu Sans
      12
    
    
      [0]
      
      0
      DejaVu Sans
      12
    
    
      1000
      
      0
      DejaVu Sans
      12
    
    
      03/11/2010 10:30:00 [seconds]
      
      0
      DejaVu Sans
      12
    
    10
    10
    4
    8
    5
    6
    7
    3
    0
    0
    0
    0
    #808080
    #808080
    1
    1
    1
    1
    1
    -1
    -1
    5
    5
    1
    0
    1
    0
    0
    0
    0
    0
    0
    0
    
    
    1
    1
    4
    0
    1
    4
    0
    0
    0
    0
    #000000
    1
    1
    1
    1
  
  
    W1
    
    
    W1
    #efefef
    
      P1
      
        
        
        Object 165
        
        
        unnamed
        #000000
        2
        #000000
        #ffffff
        0
        0
        
        1
        false
        false
        5
        true
        
        3
        5
        6
        7
        8
      
    
  

I have to say, this is a superb project. Probably the coolest application I have ever seen with the Arduino. I would be more than willing to assemble this circuit and make a nice finished product (if all the schematics are all in place…), giving you credit for the design. Very, very cool :sunglasses:

Thanks

Here's the schematic

Also interested in the pcb w/ or w/o parts kit if you make one. I’ve tried my hand at a version of this, but am interested in trying yours.

-creatrope

please do make kits... thi is awsome... ;)

very cool

Awesome work!!! way to go, this is totally amazing.

Any new updates???

I was just reading about the zeo the other day and was really hoping someone could make such a device for lucid dreaming.

I got some questions for the creator

Why did you choose to track the eye movements through the temple and not the frontal lobes?

The zeo personal sleep coach tracks the frontal lobes which are located on the forehead using foam pads which you don't need to use any gel. They said their tech which they call softwave is patented and is based on polysomnography which they say is the most reliable way of detecting sleep cycles including REM and that this is what they use in sleep labs all around the world.

The zeo is a wireless device that communicates on the 2.4mhz band, the zeo alarm clock has an sd card which all the nights sleep data is recorded onto which can then be viewed by inserting it into a PC.

Will your device work via a cable to a PC/notebook that sits by your beside table?

Can you not make a console that communicates with the headband wireleslly without needing a computer by your bed?

I see in your first post of this thread that your headband has the same tech like the remdreamer which is TWC for two way communication. The remdreamer has just got this new upgrade out which is a rem speaker that can work with TWC do you think your device could support this, the remspeaker allows you to record an audio clip which can be played when the rem sensor detects that you are dreaming.

I would love to see this device of yours being able to have the following features

wireless TWC light and beep cues audio cues console with microphone for recording audio cues (so no computer needed) 4 LED's for each eye, a light and sound machine upgrade for the future that could get your brainwaves ready for lucid dreaming. This is what the dreammaker pro has. Maybe we can forget this feature.

Anyway if you could have all those features and maybe or maybe not the last one then that would be so awesome.

I would love to see you building these as a complete unit and as well offering the flashed chip and parts for people to build it themselves.

Awesome and please keep up the great work, this is amazing work that really has got to be finished. The best idea I have seen in many years.

Thanks very much for reading

I'm very interested in this subject as well. I would like to be updated on how this is going for you.

Hi all! My friend and I are engaged in the development of devices for lucid dreaming.

Made homemade REM-Dreamer (Novadreamer) - comfortable to sleep with him does not work, the mask presses on the head hard. So we decided to move to EOG - now doing an amplifier and a processing unit for DSP-processor.

This will be a platform consisting of EOG sensors, vibrating alert, Neurophone (for submission to the voice prompts sleep), as well as sensors on the neck to remove sounds of sleep - see Chuck Jorgensen Dear merkz tell about their experiences with the EOG, let us cooperate in the field of devices for lucid dreaming.

P.S sorry for my english))) write through translator)))) ::)