Hello all,
good to hear that there is some progress on that issue.
To clear up the (non-)existance of a "start button" :
i am using the monolithEEG
http://freenet-homepage.de/moosec/proje ... age431.htm
which is compatbile to the ModularEEG in terms of transmission protocol (P2) but has a start/pause button
and a USB converter onboard. when you plug in this device, a virual COM port is created, but the transfers
is not active unless you press the button.
this is the reason why i suspected that the timeout error is related to the fact that the data transfer starts immediately
when a ModularEEG is plugged in (the RS232-buffers will be full/overflowed if the readout does not start immediately).
regards,
chris.
Problems with ModularEEG Data aquisition
-
- Posts: 6
- Joined: Wed Jul 15, 2009 10:43 pm
Re: Problems with ModularEEG Data aquisition
I am currently working on my own version of monolithEEG, so I study the schemes and firmware of both monolithEEG and modEEG.
modEEG does not have a switch (even internally and not implemented by seller, in the orginal circuit had provided one), so perhaps you can try that :
1) Connect modEEG (with power off) to PC
2) Start Acq Server and OpenVibe, without press play or connect
3) Now the tricky part, in that order and as quickly as possible : turn on modEEG, press connect, press play.
This is not convenient but it willl to identify the problem, If as Chris Veigl said it is a buffer problem.
I hope this can help.
modEEG does not have a switch (even internally and not implemented by seller, in the orginal circuit had provided one), so perhaps you can try that :
1) Connect modEEG (with power off) to PC
2) Start Acq Server and OpenVibe, without press play or connect
3) Now the tricky part, in that order and as quickly as possible : turn on modEEG, press connect, press play.
This is not convenient but it willl to identify the problem, If as Chris Veigl said it is a buffer problem.
I hope this can help.
Naëm Baron
CV : http://bee-oh.esiea-ouest.fr/baron/index.xml
CV : http://bee-oh.esiea-ouest.fr/baron/index.xml
Re: Problems with ModularEEG Data aquisition
The following posts have been moved to another dedicated topic, here.
Please create new topic for new question !
- The OpenViBE Team
Please create new topic for new question !
- The OpenViBE Team
-
- Posts: 13
- Joined: Thu Sep 10, 2009 8:44 am
Re: Problems with ModularEEG Data aquisition
Hi all
i had the same trouble with the current driver for the ModularEEG P2 in the last 2 release. maybe related to windows, i dont know.
anyway i rewrote the driver (taking example on brainbay) and it work fine for me now. here is the codes (C++) , maybe (if its validated by a majority) could it be included into the next version
marc
i had the same trouble with the current driver for the ModularEEG P2 in the last 2 release. maybe related to windows, i dont know.
anyway i rewrote the driver (taking example on brainbay) and it work fine for me now. here is the codes (C++) , maybe (if its validated by a majority) could it be included into the next version
marc
Code: Select all
#include "ovasCDriverModularEeg.h"
#include "../ovasCConfigurationGlade.h"
#include <openvibe-toolkit/ovtk_all.h>
#include <system/Time.h>
#include <math.h>
#include <iostream>
#if defined OVAS_OS_Windows
#include <windows.h>
#include <winbase.h>
#include <stdio.h>
#include <stdlib.h>
#include <commctrl.h>
#define TERM_SPEED 57600
#else
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/select.h>
#define TERM_SPEED B57600
#endif
// ModularEEG P2 drive for Windows 7 (Marc Swynghedauw) 2009
using namespace OpenViBEAcquisitionServer;
using namespace OpenViBE;
using namespace std;
//___________________________________________________________________//
// //
void CDriverModularEeg::logPacket(void)
{
uint32 ui32I;
printf("\nPacket %d received:\n",m_ui8PacketNumber);
for (ui32I=0;ui32I<6;ui32I++)
{
printf("Channel %d:%d\n",ui32I+1,m_i32ChannelBuffer[ui32I]);
}
}
uint32 CDriverModularEeg::parseByteP2(int32 PacketsProcessed, uint8 ui8Actbyte)
{
switch (m_ui16Readstate)
{
case 0: if (ui8Actbyte==165)
{
m_ui16Readstate++;
} else
{
m_ui16Readstate=0;
PacketError=true;
}
break;
case 1: if (ui8Actbyte==90)
{
m_ui16Readstate++;
}
else
{
m_ui16Readstate=0;
PacketError=true;
}
break;
case 2: m_ui16Readstate++;
m_ui8ModularVersion= ui8Actbyte;
if (m_ui8ModularVersion!=2) {
m_ui16Readstate=0;
PacketError=true;
}
break;
case 3: m_ui8PacketNumber = ui8Actbyte;
m_ui16ExtractPosition=0;
m_ui16Readstate++;
break;
case 4: if (m_ui16ExtractPosition < 12)
{
if ((m_ui16ExtractPosition & 1) == 0)
{
m_i32ChannelBuffer[m_ui16ExtractPosition>>1]= ((int32)ui8Actbyte)<<8;
}
else
{
m_i32ChannelBuffer[m_ui16ExtractPosition>>1]+=ui8Actbyte;
}
m_ui16ExtractPosition++;
}
else
{
m_ui16Switches= ui8Actbyte;
m_ui16Readstate=0;
for(uint32 j=0; j<m_oHeader.getChannelCount(); j++)
{
m_pSample[j*m_ui32SampleCountPerSentBlock+PacketsProcessed]=(float32)m_i32ChannelBuffer[j]-512;
}
//logPacket();
return true;
}
break;
default:
m_ui16Readstate=0;
}
return false;
}
uint32 CDriverModularEeg::initTty(FD_TYPE * pFileDescriptor, uint32 ui32TtyNumber)
{
uint8 l_ttyname[20];
#if defined OVAS_OS_Windows
sprintf((char *)l_ttyname,"%s%d","\\\\.\\COM",ui32TtyNumber);
DCB dcb = {0};
*pFileDescriptor = CreateFile((LPCSTR) l_ttyname,GENERIC_READ | GENERIC_WRITE,
0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if (*pFileDescriptor == INVALID_HANDLE_VALUE)
{
printf("Could not open Communication Port %s for ModulerEEG Driver.\n",(char *) l_ttyname);
return false;
}
if (!GetCommState(*pFileDescriptor, &dcb)) // get current DCB settings
{
return false;
}
// update DCB rate, byte size, parity, and stop bits size
dcb.DCBlength = sizeof(dcb);
dcb.BaudRate = CBR_57600; //TERM_SPEED;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
dcb.EvtChar = '\0';
// update flow control settings
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDsrSensitivity = FALSE;;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
dcb.fTXContinueOnXoff = FALSE;
dcb.XonChar = 0;
dcb.XoffChar = 0;
dcb.XonLim = 0;
dcb.XoffLim = 0;
dcb.fParity = FALSE;
SetCommState(*pFileDescriptor, &dcb);
SetupComm(*pFileDescriptor, 1024, 1024);
EscapeCommFunction(*pFileDescriptor, SETDTR);
SetCommMask (*pFileDescriptor, EV_RXCHAR | EV_CTS | EV_DSR | EV_RLSD | EV_RING);
#else
struct termios l_terminalAttributes;
// open ttyS<i> for i < 10, else open ttyUSB<i-10>
if (ui32TtyNumber<10)
{
sprintf((char *)l_ttyname,"%s%d","/dev/ttyS",ui32TtyNumber);
}
else
{
sprintf((char *)l_ttyname,"%s%d","/dev/ttyUSB",ui32TtyNumber-10);
}
if ((*pFileDescriptor = open((const char *)l_ttyname, O_RDWR)) == -1)
{
printf("Could not open Communication Port %s for ModulerEEG Driver.\n",(char *) l_ttyname);
return false;
}
if (tcgetattr(*pFileDescriptor, &l_terminalAttributes) != 0)
{
close (*pFileDescriptor);
*pFileDescriptor=-1;
perror("terminal: tcgetattr() failed");
return false;
}
/* term_attr.c_cflag = TERM_SPEED | CS8 | CRTSCTS | CLOCAL | CREAD; */
l_terminalAttributes.c_cflag = TERM_SPEED | CS8 | CLOCAL | CREAD;
l_terminalAttributes.c_iflag = 0;
l_terminalAttributes.c_oflag = OPOST | ONLCR;
l_terminalAttributes.c_lflag = 0;
if (tcsetattr(*pFileDescriptor, TCSAFLUSH, &l_terminalAttributes) != 0)
{
close(*pFileDescriptor);
*pFileDescriptor=-1;
perror("terminal: tcsetattr() failed");
return false;
}
#endif
return true;
}
void CDriverModularEeg::closeTty(FD_TYPE i32FileDescriptor)
{
#if defined OVAS_OS_Windows
CloseHandle(i32FileDescriptor);
#else
close (i32FileDescriptor);
#endif
}
int32 CDriverModularEeg::readPacketFromTty(FD_TYPE i32FileDescriptor)
{
uint8 l_ui8ReadBuffer[100];
uint32 l_ui32BytesProcessed;
int32 l_i32PacketsProcessed;
l_i32PacketsProcessed=0;
l_ui32BytesProcessed=0;
#if defined OVAS_OS_Windows
uint32 l_ui32ReadLength;
uint32 l_ui32ReadOk;
struct _COMSTAT l_status;
uint32 l_ui32etat;
l_ui32ReadLength = 0;
l_ui32ReadOk=0;
if (ClearCommError(i32FileDescriptor, (LPDWORD)&l_ui32etat, &l_status))
{
l_ui32ReadLength = l_status.cbInQue;
}
for (l_ui32BytesProcessed=0; l_ui32BytesProcessed < l_ui32ReadLength; l_ui32BytesProcessed++)
{
// Read the data from the serial port.
ReadFile (i32FileDescriptor, l_ui8ReadBuffer, 1, (LPDWORD)&l_ui32ReadOk, 0);
if (l_ui32ReadOk==1)
{
if (parseByteP2(l_i32PacketsProcessed, l_ui8ReadBuffer[0]))
{
l_i32PacketsProcessed++;
}
}
}
#else
fd_set l_inputFileDescriptorSet;
struct timeval l_timeout;
ssize_t l_ui32ReadLength=0;
l_timeout.tv_sec=1;
l_timeout.tv_usec=0;
FD_ZERO(&l_inputFileDescriptorSet);
FD_SET(i32FileDescriptor, &l_inputFileDescriptorSet);
switch (select(i32FileDescriptor+1, &l_inputFileDescriptorSet, NULL, NULL, &l_timeout))
{
case -1: // error or timeoutASQAVWQ<QSDFG
case 0: return (-1);
default:
if (FD_ISSET(i32FileDescriptor, &l_inputFileDescriptorSet))
{
if ((l_ui32ReadLength = read(i32FileDescriptor, l_ui8ReadBuffer, 1)) > 0)
{
for (l_ui32BytesProcessed=0; l_ui32BytesProcessed < l_ui32ReadLength; l_ui32BytesProcessed++)
{
if (parseByteP2(l_ui8ReadBuffer[l_ui32BytesProcessed]))
{
l_i32PacketsProcessed++;
} QRcfxdq<qwDFDWQ²HBCVXDQw<gcxcfdsw<²
}
}
}
}
#endif
return(l_i32PacketsProcessed);
}
//___________________________________________________________________//
// //
CDriverModularEeg::CDriverModularEeg(IDriverContext& rDriverContext)
:IDriver(rDriverContext)
,m_pCallback(NULL)
,m_bInitialized(false)
,m_bStarted(false)
,m_ui32SampleCountPerSentBlock(0)
,m_pSample(NULL)
,m_ui32TotalSampleCount(0)
,m_ui32StartTime(0)
{
m_oHeader.setExperimentIdentifier(4);
m_oHeader.setSamplingFrequency(256);
m_oHeader.setChannelCount(6);
}
void CDriverModularEeg::release(void)
{
delete this;
}
const char* CDriverModularEeg::getName(void)
{
return "Modular EEG P2";
}
//___________________________________________________________________//
// //
OpenViBE::boolean CDriverModularEeg::initialize(
const uint32 ui32SampleCountPerSentBlock,
IDriverCallback& rCallback)
{
if(m_bInitialized)
{
return false;
}
if(!m_oHeader.isChannelCountSet()
||!m_oHeader.isSamplingFrequencySet())
{
return false;
}
m_ui16Readstate=0;
m_ui16ExtractPosition=0;
if (!initTty(&m_i32FileDescriptor, m_oHeader.getExperimentIdentifier()))
{
return false;
}
m_pSample=new float32[m_oHeader.getChannelCount()*ui32SampleCountPerSentBlock];
if(!m_pSample)
{
delete [] m_pSample;
m_pSample=NULL;
return false;
}
m_pCallback=&rCallback;
m_bInitialized=true;
m_ui32SampleCountPerSentBlock=ui32SampleCountPerSentBlock;
m_ui32TotalSampleCount=0;
m_ui8LastPacketNumber=0;
printf("ModulerEEG Device Driver initialized.\n");
m_ui32StartTime=System::Time::getTime();
return true;
}
OpenViBE::boolean CDriverModularEeg::start(void)
{
if(!m_bInitialized)
{
return false;
}
if(m_bStarted)
{
return false;
}
printf("ModulerEEG Device Driver started.\n");
indexBuffer=-1;
dwBytesTransferred=0;
m_bStarted=true;
l_i32PacketsProcessed=0;
isRunning=false;
PacketError=false;
return m_bStarted;
}
OpenViBE::boolean CDriverModularEeg::loop(void)
{
if(!m_bInitialized)
{
return false;
}
if(!m_bStarted)
{
return false;
}
// uint32 l_ui32CurrentTime=System::Time::getTime();
CStimulationSet l_oStimulationSet;
l_oStimulationSet.setStimulationCount(1);
l_oStimulationSet.setStimulationIdentifier(0, 0);
l_oStimulationSet.setStimulationDate(0, 0);
l_oStimulationSet.setStimulationDuration(0, 0);
uint32 l_i32ReceivedSamples=0;
uint32 l_ui32ReadLength;
uint32 l_ui32ReadOk;
struct _COMSTAT l_status;
//uint8 l_ui8ReadBuffer[100];
uint32 l_ui32etat;
// bytes actually read
uint32 IndexStart;
if (indexBuffer<=0) {
if (ClearCommError(m_i32FileDescriptor, (LPDWORD)&l_ui32etat, &l_status))
{
dwBytesTransferred = l_status.cbInQue;
}
dwRead=0;
l_oStimulationSet.setStimulationCount(0);
if (dwBytesTransferred) {
ReadFile (m_i32FileDescriptor, l_ui8ReadBuffer_New, dwBytesTransferred, &dwRead, 0);
l_oStimulationSet.setStimulationCount(0);
if (!isRunning) {
printf("ModulerEEG Device Driver Receiving Data...\n");
isRunning=true;
}
}
IndexStart=0;
} else {
IndexStart=indexBuffer;
l_oStimulationSet.setStimulationCount(0);
}
if (dwRead) {
for (uint32 l_ui32BytesProcessed=IndexStart; l_ui32BytesProcessed < dwRead; l_ui32BytesProcessed++)
{
if (parseByteP2(l_i32PacketsProcessed, l_ui8ReadBuffer_New[l_ui32BytesProcessed]))
{
l_i32PacketsProcessed++;
m_ui8LastPacketNumber=m_ui8PacketNumber;
if ( l_i32PacketsProcessed >= m_ui32SampleCountPerSentBlock) {
m_ui32TotalSampleCount+=l_i32PacketsProcessed;
l_oStimulationSet.setStimulationCount(0);
if (PacketError)
l_oStimulationSet.setStimulationCount(1);
m_pCallback->setSamples(m_pSample);
m_pCallback->setStimulationSet(l_oStimulationSet);
l_i32PacketsProcessed=0;
//printf("Sending %d.........%d %d start=%d pos=%d\n",m_ui32SampleCountPerSentBlock, dwRead, dwBytesTransferred, IndexStart , l_ui32BytesProcessed );
indexBuffer=l_ui32BytesProcessed+1;
PacketError=false;
if (l_ui32BytesProcessed == dwRead-1) {
l_i32PacketsProcessed=0;
indexBuffer=-1;
}
return true;
} else {
if (l_ui32BytesProcessed == dwRead-1) {
// m_ui32TotalSampleCount+=l_i32PacketsProcessed;
//m_pCallback->setSamples(m_pSample);
//m_pCallback->setStimulationSet(l_oStimulationSet);
// printf("1/ Sending smaller sample %d\n",l_i32PacketsProcessed);
//l_i32PacketsProcessed=0;
indexBuffer=-1;
return true;
}
}
} else {
if (l_ui32BytesProcessed == dwRead-1) {
// m_ui32TotalSampleCount+=l_i32PacketsProcessed;
// printf("2/ Sending smaller sample %d\n",l_i32PacketsProcessed);
//l_oStimulationSet.setStimulationCount(0);
//m_pCallback->setSamples(m_pSample);
//m_pCallback->setStimulationSet(l_oStimulationSet);
//l_i32PacketsProcessed=0;
indexBuffer=-1;
}
}
}
}
return true;
}
OpenViBE::boolean CDriverModularEeg::loop_old(void)
{
if(!m_bInitialized)
{
return false;
}
if(!m_bStarted)
{
return false;
}
// uint32 l_ui32CurrentTime=System::Time::getTime();
CStimulationSet l_oStimulationSet;
l_oStimulationSet.setStimulationCount(1);
l_oStimulationSet.setStimulationIdentifier(0, 0);
l_oStimulationSet.setStimulationDate(0, 0);
l_oStimulationSet.setStimulationDuration(0, 0);
uint32 l_i32ReceivedSamples=0;
int32 l_i32PacketsProcessed;
while ( l_i32ReceivedSamples < m_ui32SampleCountPerSentBlock )
{
l_i32PacketsProcessed=readPacketFromTty(m_i32FileDescriptor);
switch (l_i32PacketsProcessed)
{
case 0: // no Packet finished
break;
case 1: // Packet with Samples arrived
// m_ui8LastPacketNumber++;
// if (m_ui8LastPacketNumber != m_ui8PacketNumber)
// printf("expected %d, received: %d\n",m_ui8LastPacketNumber,m_ui8PacketNumber);
m_ui8LastPacketNumber=m_ui8PacketNumber;
for(uint32 j=0; j<m_oHeader.getChannelCount(); j++)
{
m_pSample[j*m_ui32SampleCountPerSentBlock+l_i32ReceivedSamples]=(float32)m_i32ChannelBuffer[j]-512;
}
l_i32ReceivedSamples++;
break;
case -1: // Timeout, could inidicate communication error
return false;
}
}
m_ui32TotalSampleCount+=m_ui32SampleCountPerSentBlock;
printf("sending %d.\n", l_i32ReceivedSamples);
m_pCallback->setSamples(m_pSample);
m_pCallback->setStimulationSet(l_oStimulationSet);
return true;
}
OpenViBE::boolean CDriverModularEeg::stop(void)
{
if(!m_bInitialized)
{
return false;
}
if(!m_bStarted)
{
return false;
}
printf("ModulerEEG Device Driver stopped.\n");
m_bStarted=false;
isRunning=false;
return !m_bStarted;
}
OpenViBE::boolean CDriverModularEeg::uninitialize(void)
{
if(!m_bInitialized)
{
return false;
}
if(m_bStarted)
{
return false;
}
m_bInitialized=false;
closeTty (m_i32FileDescriptor);
printf("ModulerEEG Device Driver closed.\n");
delete [] m_pSample;
m_pSample=NULL;
m_pCallback=NULL;
return true;
}
//___________________________________________________________________//
// //
OpenViBE::boolean CDriverModularEeg::isConfigurable(void)
{
return true;
}
OpenViBE::boolean CDriverModularEeg::configure(void)
{
CConfigurationGlade m_oConfiguration("../share/openvibe-applications/acquisition-server/interface-Modular-Eeg.glade");
return m_oConfiguration.configure(m_oHeader);
}
Re: Problems with ModularEEG Data aquisition
Warm thanks !
we will take a closer look at this driver as soon as possible.
If anyone has feedback to provide, feel free to post a comment !
Laurent
we will take a closer look at this driver as soon as possible.
If anyone has feedback to provide, feel free to post a comment !
Laurent
Re: Problems with ModularEEG Data aquisition
Dear mswynghedauw,mswynghedauw wrote:Hi all
i had the same trouble with the current driver for the ModularEEG P2 in the last 2 release. maybe related to windows, i dont know.
anyway i rewrote the driver (taking example on brainbay) and it work fine for me now. here is the codes (C++) , maybe (if its validated by a majority) could it be included into the next version
marc
thank you for your contribution. the problem was a mix of the driver not being able to handle more than 1 P2 packet and Windows having a big buffer on COM ports. I quickly fixed that for students couple of weeks ago but did not have time to release it in the SVN. I will try to get best of the two implementations.
Thanks again,
Yann