Sie sind auf Seite 1von 9

/* Author: Brendan Flynn

Date : last mod = May 13, 2014


Summary : Arduino driver for FlexVolt Shield.
Sends data measured on analog inputs to PC via Serial Comm Port
Physical Inputs : 4 analog inputs, reading raw 10-bit signals from FlexVolt Shi
eld
Outputs: measured signals, raw or filtered
Note All commands are echoed back. On computer side, wait for echo to confirm
receipt
*/
/////////// Port Mapping //////////////
int chan1 = A3;
int chan2 = A2;
int chan3 = A1;
int chan4 = A0;
int analogPins[] = {
chan1, chan2, chan3, chan4}; // array for loops
int tipswitch1 = 5;
int tipswitch2 = 4;
int tipswitch3 = 3;
int tipswitch4 = 2;
int tipSwitches[] = {
tipswitch1, tipswitch2, tipswitch3, tipswitch4};
// constants
const int VERSION = 2;
const int MODELNUMBER = 0;
// Timing //
// for computer control of sample frequency, just send data every time computer
sends 'M'
//
// for Arduino control of sample frequency
// adjustable from computer:
int TimingOffset = -6; // Arduino takes 6 us to execute command - offest for acc
uracy
const int UserFreqArray[] = {
1, 10, 50, 100, 200, 300, 400, 500, 1000, 1500, 2000, 4000};
int UserFreqIndex = 8;
int UserFrequency = UserFreqArray[UserFreqIndex];//Hz //modify from computer app
int MaxCustomFreq = 4000; // most signals are in the 100 Hz region.
// Frequency: 1-2kHz works well. 4kHz pushes timing limits and requires some
tweaking.
// Calculate Timing Delay Between Samples:
long measurementdelay = 1000000/long(UserFrequency);// converted to microseconds
// Control Flags
boolean sendflag = false;
boolean dataflag = false;
boolean settingsflag = false;
boolean sendFiltered = false; // flags for data type to send
boolean sendRaw = true; // flags for data tye to send
// Control Register

const int REGsize = 9;


char REG[REGsize];
char tmpREG[REGsize];
char REGindex = 0;
// Register variables
int NChan = 4;
int BitDepth = 10;
int DownSampleCount = 0;
int downsampleCounter = 0;
const int DownSampleCountMax = 100;
const int DownSampleCountMin = 0;
// Control
//REG0
const char
const char
const char
const char
//REG1
const char

Register Masks
ChannelMask =
FreqIndexMask=
DataModeMask =
BitDepthMask =

0b11000000;
0b00111100;
0b00000010;
0b00000001;

FilterShiftValMask = 0b00011111;

/////////// Variables ///////////


long updatetime = 0; // timer variable
/* ------------- Plug Testing ---------------- */
const int MaxPlugTestDelay = 100;
int PlugTestDelay = 1;//Hz - check Jack tip switches for plugs
int PlugTestCount = 100;//(UserFrequency*PlugTestDelay)/10; count this high befo
re checking again
int PlugTestCounter = 0; // increments every datasend
int tipswitchcountN = 10;// 1/countN HIGH = true for Arduino digitalRead(2.5V)
int tipswitchCounter = 0;
byte tipswitchvals = 0;
boolean PlugTestFlag = false;
/* ------------- Smoothing Filter ---------------- */
int MaxFilterShift = 30; // 8 is usually a good value
unsigned long filter_reg[] = {
0,0,0,0};
int FilterShiftValdefault = 8;
int FilterShiftVal = FilterShiftValdefault; //10 too high at 1000Hz
// http://www.edn.com/design/systems-design/4320010/A-simple-software-lowpass-fi
lter-suits-embedded-system-applications
void setup(void){
// set pin modes
for(int i = 0; i < NChan; i++){ // loop through channels
pinMode(analogPins[i],INPUT);
pinMode(tipSwitches[i],INPUT);
}
// establish com
Serial.begin(230400); // set baud rate.
}
void loop(){
if (dataflag){ // Arduino-controlled timing & measurement

if (micros() > updatetime){ // check if it's time to send next sample


updatetime = micros()+measurementdelay-TimingOffset; // reset timer.
ProcessOutput(); // handles data formats, filters, and channels
}
}
if(PlugTestFlag){
PlugTestCounter++;
if (PlugTestCounter >= PlugTestCount){
TestPlugs();
PlugTestCounter = 0;
}
}
}
// Serial port listener - must handshake before sending data ////////
void serialEvent() {
if (Serial.available() >= 0) {
char inChar = Serial.read();
Serial.write(inChar);
if (!sendflag){
if (inChar == 'A') {// computer controlled timing - measure every 'M' from
computer
Serial.write('a');
return;
}
if (inChar == '1') {// computer controlled timing - measure every 'M' from
computer
sendflag = true;
Serial.write('b');
return;
}
if (inChar == 'X') {// computer controlled timing - measure every 'M' from
computer
DataOff();
sendflag = false;
settingsflag = false;
Serial.write('x');
return;
}
else {
SendError('s',inChar);
return;
}
}
else if(sendflag){
if (settingsflag){
if (REGindex < REGsize){
tmpREG[REGindex] = inChar;
Serial.write(REGindex);
Serial.write(inChar);
REGindex++;
if (REGindex == REGsize){
Serial.write('y');
}
return;
}
else if (REGindex >= REGsize){
settingsflag = false;
if (inChar != 'Y') { // Quit. stop. can still measure and send using
computer control (see case 'M')

DataOff(); // set flag to computer controlled timing


Serial.write('q');
return;
}
else if(inChar == 'Y'){
for (int i = 0; i < REGsize; i++){
REG[i] = tmpREG[i];
}
UpdateSettings();
Serial.write('z');
return;
}
}
}
else if (!settingsflag){
if (inChar == 'M') {// computer controlled timing - measure every 'M' fr
om computer
ProcessOutput(); // handles data formats, filters, and channels
DataOff();
return;
}
else if (inChar == 'G'){ // Go. make with the measuring and sending of
data! Arduino controlled
Serial.write('g');
DataOn();
updatetime = micros()+measurementdelay-TimingOffset; // initialize tim
er
return;
}
else if (inChar == 'Q') { // Quit. stop. can still measure and send us
ing computer control (see case 'M')
Serial.write('q');
DataOff();
return;
}
if (inChar == 'X') { // Quit. stop. can still measure and send using c
omputer control (see case 'M')
DataOff(); // set flag to computer controlled timing
settingsflag = false;
Serial.write('x');
return;
}
else if (inChar == 'S') { // enter settings menu
DataOff(); // set Arduino controlled timing off for menu handling
Serial.write('s');
settingsflag = true;
REGindex = 0;
return;
}
else if (inChar == 'V') { // enter settings menu
DataOff(); // set Arduino controlled timing off for menu handling
Serial.write('v');
SendVersionInfo();
return;
}
if (inChar == 'A'){ // always receive upper case
DataOff();
Serial.write('a'); // always send back lower case
sendflag = false;
return;

}
else { // handle all other unknown input values
SendError('d',inChar);
DataOff(); // set flag to stop sending data and sort out confusion
return;
}
} // end of if !settingsflag
} // end of if sendflag
} // end of if serial available
} // end of function
void DataOff(void){
dataflag = false;
}
void DataOn(void){
long tmpL = 128 << FilterShiftVal;
for (int i = 0; i<NChan; i++){
filter_reg[i]=tmpL;
}
// initialize timing and start counter
// Now update dependent variables that may have changed
long measurementdelay = 1000000/long(UserFrequency);// converted to microsecon
ds
downsampleCounter = 0; // for downsampling
updatetime = micros()+measurementdelay-TimingOffset; // reset timer.
dataflag = true;
}
void send10BitRawVals(void){
int tmp = 0;
int val = 0;
if (NChan == 1){
Serial.write('H');
}
else if (NChan == 2){
Serial.write('I');
}
else if (NChan == 4){
Serial.write('J'); // highlight next
}
for (int i = 0; i<NChan; i++){ // loop
val = analogRead(analogPins[i]); //
val = val << 6;
Serial.write(highByte(val)); // 0000
tmp += (lowByte(val)>>(2*i));
}
Serial.write(lowByte(tmp));
}
void send8BitRawVals(void){
int val = 0;
if (NChan == 1){
Serial.write('C');
}
else if (NChan == 2){
Serial.write('D');
}

data packet
through channels
read channel. 10-bit ADC. returns int
00** high byte is mostly 0's

else if (NChan == 4){


Serial.write('E'); // highlight next data packet
}
for (int i = 0; i<NChan; i++){ // loop through channels
val = analogRead(analogPins[i]); // read channel. 10-bit ADC. returns int
val = val >> 2;
Serial.write(val); // 0000 00** high byte is mostly 0's
}
}
void send8BitFilteredVals(void){
int val = 0;
downsampleCounter ++;
if (downsampleCounter < DownSampleCount){
for (int i = 0; i<NChan; i++){ // loop through channels
val = analogRead(analogPins[i]); // read channel. 10-bit ADC. returns i
nt
val = val >> 2;
filter_reg[i] = filter_reg[i] - (filter_reg[i] >> FilterShiftVal) + long(a
bs(val-128)+128);
}
}
else if(downsampleCounter >= DownSampleCount){
downsampleCounter = 0;
if (NChan == 1){
Serial.write('C');
}
else if (NChan == 2){
Serial.write('D');
}
else if (NChan == 4){
Serial.write('E'); // highlight next data packet
}
for (int i = 0; i<NChan; i++){ // loop through channels
val = analogRead(analogPins[i]); // read channel. 10-bit ADC. returns i
nt
val = val >> 2;
filter_reg[i] = filter_reg[i] - (filter_reg[i] >> FilterShiftVal) + long(a
bs(val-128)+128);
//
val = filter_reg[i];// >> FilterShiftVal;
val = int(filter_reg[i] >> FilterShiftVal); // FilterShiftVal can be adjus
ted!
Serial.write(val); //
}
}
}
void ProcessOutput(void){
if (sendRaw){
if (BitDepth == 10){
send10BitRawVals();
}
if (BitDepth == 8){
send8BitRawVals();
}
}
else if(sendFiltered){
send8BitFilteredVals();
}
}

void SendVersionInfo(void){
Serial.write(VERSION);
Serial.write(0);
Serial.write(0);
Serial.write(MODELNUMBER);
}
void UpdateSettings(void){
/*
* Control Words
*
* REG0 = main/basic user settings
* REG0<7:6> = Channels, 11=8, 10=4, 01=2, 00=1
* REG0<5:2> = FreqIndex
* REG0<1> = DataMode (1 = filtered, 0 = raw)
* REG0<0> = Data bit depth. 1=10bits, 0 = 8bits
*
* REG1 = Filter Shift Val + Prescalar Settings
* REG1<4:0> = filter shift val, 0:31, 5-bits
* REG1<7:5> = PS setting.
*
000 = 2
*
001 = 4
*
010 = 8
*
011 = 16 // not likely to be used
*
100 = 32 // not likely to be used
*
101 = 64 // not likely to be used
*
110 = 128// not likely to be used
*
111 = off (just use 48MHz/4)
*
* REG2 = Manual Frequency, low byte (16 bits total)
* REG3 = Manual Frequency, high byte (16 bits total)
*
* REG4 = Time adjust val (8bits, -6:249)
*
* REG5 & REG6 Timer Adjustment
* (add Time Adjust to x out of N total counts to 250)
* REG5<7:0> = partial counter val, low byte, 16 bits total
* REG6<7:0> = partial counter val, high byte, 16 bits total
*
* REG7<7:0> = down sampling value (mainly for smoothed data)
*
* REG8<7:0> = Plug Test Frequency
*/
int tmp = 0;
int tmp2 = 0;
//REG0
tmp = REG[0]&ChannelMask;
tmp = tmp>>6;
//
if (tmp == 3){NChan = 8;}
if (tmp == 2){
NChan = 4;
}
if (tmp == 1){
NChan = 2;
}
if (tmp == 0){
NChan = 1;
}

tmp = REG[0]&FreqIndexMask;
tmp = tmp>>2;
if (tmp >= 0 && tmp < sizeof(UserFreqArray)){ // handle out of bounds
UserFreqIndex = tmp;
UserFrequency = UserFreqArray[UserFreqIndex]; // store new frequency
measurementdelay = 1000000/long(UserFrequency);
}
else {
SendError('I',tmp);
}
tmp = REG[0]&DataModeMask;
if(tmp>0){
sendRaw = false;
sendFiltered = true;
}
else if(tmp == 0){
sendFiltered = false;
sendRaw = true;
}
tmp = REG[0]&BitDepthMask;
if(tmp == 0){
BitDepth = 8;
}
else if(tmp > 0){
BitDepth = 10;
}
// REG1
tmp = REG[1]&FilterShiftValMask;
if (tmp >= 0 && tmp <= MaxFilterShift){
FilterShiftVal = tmp;
}
else{
SendError('f',tmp);
}
//

tmp = REG[1]; // for USB/Bluetooth versions

// REG2,3 Custom Frequency. Overwrites If UserFrequency is > 0


tmp = REG[3];
tmp = tmp<<8;
tmp2 = REG[2];
tmp += tmp2;
if (tmp > 0 && tmp < MaxCustomFreq){
UserFrequency = tmp;
}
// REG4 Timer0 Adjust Value
TimingOffset = REG[4]-6;//shift it with the -6
// REG5, 6 Timer0 Adjust Value Partial count implementation
tmp = REG[6];
tmp = tmp << 8;
tmp2 = REG[5];
Timer0PartialCounter = tmp + tmp2;

//
//
//
//

// REG 7 Downsampling. Transmit a lower datarate, especially for smoothed sig

nal
tmp = REG[7];
if (tmp >= DownSampleCountMin && tmp <= DownSampleCountMax){
DownSampleCount = tmp;
}
downsampleCounter = 0;
// REG8 PlugTest. Delay = number of seconds. if 0, no plugtest
tmp = REG[8];
if (tmp == 0){
PlugTestFlag = false;
}
if (tmp > 0 && tmp < MaxPlugTestDelay){
PlugTestFlag = true;
PlugTestDelay = tmp;
PlugTestCount = (UserFrequency*PlugTestDelay)/10; // note the divide by 10!!
if (PlugTestCount <= 0){
PlugTestCount = 1;
}
}
}
void TestPlugs(void){
byte mask = 00000001;
for(int i = 0; i < NChan; i++){ // loop through channels
if(digitalRead(tipSwitches[i]) == HIGH){
tipswitchvals = tipswitchvals | mask;
mask = mask << 1;
}
}
tipswitchCounter++;
if (tipswitchCounter >= tipswitchcountN){
Serial.write('p');
Serial.write(tipswitchvals);
tipswitchvals = 0;
tipswitchCounter = 0;
}
}
void SendError(char code, char msg){
Serial.write('e');
Serial.write(code);
Serial.write(msg);
}

Das könnte Ihnen auch gefallen