Components and supplies
Arduino UNO
Jumper wires (generic)
Apps and platforms
Simple Device Model
Arduino IDE
Project description
Code
uartdemo_sketch.ino
arduino
1/* 2 * ADC sampling decimation factor. Only one of each DECIMATION_FACTOR 3 * samples will be written to the buffer. Increase this value if you 4 * are having problems with communication reliability. 5 * 6 * The sampling frequency (in Hz) will be: 7 * 8 * Fs = 16000000 (CPU clock frequency) / 128 (ADC prescaler) / 9 * 13 (cycles per conversion) / DECIMATION_FACTOR 10 */ 11 12#define DECIMATION_FACTOR 2 13 14/* 15 * A circular buffer to store up to 256 ADC samples. Indexes are of 16 * "byte" type to make buffer overrun impossible. 17 */ 18 19volatile unsigned int adcBuffer[256]; 20volatile byte adcWriteIndex=0; 21byte adcReadIndex=0; 22volatile bool triggered=false; 23 24/* Digital pin states */ 25 26byte pinState[14]; 27byte pinPWM[14]; 28 29/* Synchronization settings */ 30 31volatile byte syncMode=0; /* 0 - off, 1 - rising edge, 2 - falling edge */ 32volatile byte syncSource=0; /* 0 - analog input, >0 - digital pin */ 33volatile unsigned int syncLevel=512; /* signal level for the oscilloscope to trigger */ 34byte syncOffset=128; /* how many samples before the trigger event will be displayed */ 35 36/* Packet size setting */ 37 38unsigned int packetSize=512; 39 40void setup() { 41/* 42 * Configure the ADC 43 * ADMUX: REFS=01 (use AVCC for reference), MUX=0000 (use ADC0 input) 44 * ADCSRB: ADTS=000 (free running mode, the new conversion will be started 45 * immediately after the previous one has been completed) 46 * ADCSRA: ADEN=1 (enable ADC), ADSC=1 (start conversion), 47 * ADATE=1 (enable auto trigger), ADIE=1 (enable ADC interrupt), 48 * ADPS=111 (set ADC prescaler to 128) 49 */ 50 ADMUX=0x40; 51 ADCSRB=0; 52 ADCSRA=0xEF; 53 Serial.begin(115200); 54} 55 56void loop() { 57/* Buffer for incoming data, can hold up to 3 bytes */ 58 static byte cmdBuffer[3]; 59 static byte cmdBytes=0; 60 61 if(Serial.available()) { 62/* Process incoming data */ 63 byte ch=Serial.read(); 64 if(cmdBytes==0) { 65/* Look for a start of a packet */ 66 if(ch==0x50||ch==0x51) { 67 cmdBuffer[0]=ch; 68 cmdBytes++; 69 } 70 } 71 else { 72/* Packet continuation */ 73 cmdBuffer[cmdBytes]=ch; 74 cmdBytes++; 75 } 76 77 if(cmdBuffer[0]==0x50&&cmdBytes==3) { 78/* Write register */ 79 writeVirtualRegister(cmdBuffer[1],cmdBuffer[2]); 80 cmdBytes=0; 81 } 82 else if(cmdBuffer[0]==0x51&&cmdBytes==2) { 83/* Read register */ 84 byte data=readVirtualRegister(cmdBuffer[1]); 85 byte buf[2]; 86 buf[0]=0x80|(data>>4); /* upper 4 bits */ 87 buf[1]=data&0x0F; /* lower 4 bits */ 88 Serial.write(buf,2); 89 cmdBytes=0; 90 } 91 } 92 else if(adcWriteIndex!=adcReadIndex) { 93/* No incoming data, transmit data from the ADC circular buffer if present */ 94 static unsigned int sampleCnt=0; 95 byte queue=adcWriteIndex-adcReadIndex; 96 if(sampleCnt==0&&syncMode!=0) { /* start of packet, wait for trigger */ 97 if(queue<syncOffset) { 98 triggered=false; 99 return; 100 } 101 if(!triggered) { 102 if(queue>syncOffset) adcReadIndex++; 103 return; 104 } 105 } 106 unsigned int data=adcBuffer[adcReadIndex++]; 107 byte buf[2]; 108 buf[0]=0xC0|(data>>5); /* upper 5 bits */ 109 if(sampleCnt==0) buf[0]|=0x20; /* start of packet mark */ 110 buf[1]=data&0x1F; /* lower 5 bits */ 111 Serial.write(buf,2); 112 if(++sampleCnt>=packetSize) sampleCnt=0; 113 triggered=false; 114 } 115} 116 117void writeVirtualRegister(byte addr,byte data) { 118/* ADC input channel */ 119 if(addr==0) ADMUX=(ADMUX&0xF0)|(data&0x0F); 120/* ADC reference voltage */ 121 else if(addr==1) ADMUX=(ADMUX&0x3F)|(data<<6); 122/* Pin mode registers */ 123 else if(addr>=2&&addr<=13) { 124 pinState[addr]=data; 125 setPinState(addr); 126 } 127/* PWM value registers */ 128 else if(addr>=18&&addr<=29) { 129 pinPWM[addr-16]=data; 130 setPinState(addr-16); 131 } 132/* Synchronization settings and packet size */ 133 else if(addr==32) syncMode=data; 134 else if(addr==33) syncSource=data; 135 else if(addr==34) syncLevel=static_cast<unsigned int>(data)<<2; 136 else if(addr==35) syncOffset=data; 137 else if(addr==36) reinterpret_cast<byte*>(&packetSize)[0]=data; 138 else if(addr==37) reinterpret_cast<byte*>(&packetSize)[1]=data; 139} 140 141byte readVirtualRegister(byte addr) { 142 if(addr==0) return ADMUX&0x0F; 143 else if(addr==1) return ADMUX>>6; 144 else if(addr>=2&&addr<=13) return pinState[addr]; 145 else if(addr>=18&&addr<=29) return pinPWM[addr-16]; 146 else if(addr==32) return syncMode; 147 else if(addr==33) return syncSource; 148 else if(addr==34) return static_cast<byte>(syncLevel>>2); 149 else if(addr==35) return syncOffset; 150 else if(addr==36) return reinterpret_cast<byte*>(&packetSize)[0]; 151 else if(addr==37) return reinterpret_cast<byte*>(&packetSize)[1]; 152 return 0; 153} 154 155void setPinState(byte pin) { 156 switch(pinState[pin]) { 157 case 0: /* input */ 158 pinMode(pin,INPUT); 159 break; 160 case 1: /* input_pullup */ 161 pinMode(pin,INPUT_PULLUP); 162 break; 163 case 2: /* force low */ 164 pinMode(pin,OUTPUT); 165 digitalWrite(pin,LOW); 166 break; 167 case 3: /* force high */ 168 pinMode(pin,OUTPUT); 169 digitalWrite(pin,HIGH); 170 break; 171 case 4: /* PWM */ 172 analogWrite(pin,pinPWM[pin]); 173 break; 174 } 175} 176 177/* Process the ADC interrupt */ 178 179ISR(ADC_vect) { 180 static byte cnt=0; 181 static unsigned int old_sample=0; 182 if(++cnt==DECIMATION_FACTOR) cnt=0; 183 if(cnt==0) { 184 unsigned int sample=ADCL|(ADCH<<8); 185/* Check trigger conditions */ 186 if(syncSource==0) { /* trigger by the analog input */ 187 if(syncMode==1&&sample>=syncLevel&&old_sample<syncLevel) triggered=true; 188 else if(syncMode==2&&sample<=syncLevel&&old_sample>syncLevel) triggered=true; 189 old_sample=sample; 190 } 191 else { /* trigger by a digital input */ 192 unsigned int s=digitalRead(syncSource); 193 if(syncMode==1&&s==HIGH&&old_sample==LOW) triggered=true; 194 else if(syncMode==2&&s==LOW&&old_sample==HIGH) triggered=true; 195 old_sample=s; 196 } 197 adcBuffer[adcWriteIndex++]=sample; 198 } 199} 200
Comments
Only logged in users can leave comments
catharanthus
0 Followers
•0 Projects
0