added code to transmit sample frequency along with sample data (more compatibility between arduino and PC, and possibility to change sampling rate at run-time)
This commit is contained in:
parent
d0ef4ee9f9
commit
ef01fe74bb
@ -7,6 +7,7 @@
|
||||
|
||||
// how many samples we want to skip between two samples we keep (can be used to lower the sampling frequency)
|
||||
#define SkipSamples 0
|
||||
byte regularEncodedFrequency;
|
||||
|
||||
const int BufferSize = 512;
|
||||
byte buffer1[BufferSize];
|
||||
@ -38,11 +39,19 @@ void setup()
|
||||
ADMUX |= (1 << REFS0); //set reference voltage
|
||||
ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only
|
||||
|
||||
ADCSRA |= (1 << ADPS2) | (0 << ADPS1) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500KHz ; 13 cycles for a conversion which means 38000 samples per second
|
||||
int ADPS = (1 << ADPS2) | (0 << ADPS1) | (1 << ADPS0);
|
||||
ADCSRA |= ADPS; //set ADC clock with 32 prescaler- 16mHz/32=500KHz ; 13 cycles for a conversion which means 38000 samples per second
|
||||
ADCSRA |= (1 << ADATE); //enabble auto trigger
|
||||
ADCSRA |= (1 << ADIE); //enable interrupts when measurement complete
|
||||
ADCSRA |= (1 << ADEN); //enable ADC
|
||||
ADCSRA |= (1 << ADSC); //start ADC measurements
|
||||
|
||||
regularEncodedFrequency = (byte)ADPS;
|
||||
byte skipSamples = 0;
|
||||
#if SkipSamples > 0
|
||||
skipSamples = SkipSamples;
|
||||
#endif
|
||||
regularEncodedFrequency |= skipSamples << 3;
|
||||
|
||||
sei();//enable interrupts
|
||||
|
||||
@ -63,7 +72,9 @@ void loop()
|
||||
digitalWrite(LEDPin, LOW);
|
||||
|
||||
//Serial.write(currentBuffer, currentBufferSize);
|
||||
oscilloscope.write(currentBuffer, currentBufferSize, currentBufferStartTime);
|
||||
oscilloscope.beginWrite(currentBufferSize + 1, currentBufferStartTime);
|
||||
oscilloscope.continueWrite(®ularEncodedFrequency, 1);
|
||||
oscilloscope.continueWrite(currentBuffer, currentBufferSize);
|
||||
}
|
||||
|
||||
ISR(ADC_vect) {//when new ADC value ready
|
||||
|
@ -23,16 +23,26 @@ SerialChannel::SerialChannel(const char* name_)
|
||||
|
||||
void SerialChannel::write(byte* data, short byteCount, unsigned long time)
|
||||
{
|
||||
if (time == (unsigned long)-1)
|
||||
time = micros();
|
||||
|
||||
handleConnection();
|
||||
beginWrite(byteCount, time);
|
||||
continueWrite(data, byteCount);
|
||||
}
|
||||
|
||||
Serial.write("START");
|
||||
Serial.write(id);
|
||||
writeULong(time);
|
||||
writeShort(byteCount);
|
||||
Serial.write(data, byteCount);
|
||||
void SerialChannel::beginWrite(short byteCount, unsigned long time)
|
||||
{
|
||||
if (time == (unsigned long)-1)
|
||||
time = micros();
|
||||
|
||||
handleConnection();
|
||||
|
||||
Serial.write("START");
|
||||
Serial.write(id);
|
||||
writeULong(time);
|
||||
writeShort(byteCount);
|
||||
}
|
||||
|
||||
void SerialChannel::continueWrite(byte* data, short byteCount)
|
||||
{
|
||||
Serial.write(data, byteCount);
|
||||
}
|
||||
|
||||
void SerialChannel::write(const char* text, unsigned long time)
|
||||
|
@ -17,6 +17,9 @@ public:
|
||||
void write(byte* data, short byteCount, unsigned long time = (unsigned long)-1);
|
||||
|
||||
void write(const char* text, unsigned long time = (unsigned long)-1);
|
||||
|
||||
void beginWrite(short byteCount, unsigned long time = (unsigned long)-1);
|
||||
void continueWrite(byte* data, short byteCount);
|
||||
|
||||
private:
|
||||
void handleConnection();
|
||||
|
@ -85,7 +85,8 @@ namespace SerialMonitor
|
||||
MainWindowContext.Get.WriteLine(text);
|
||||
break;
|
||||
case "oscilloscope":
|
||||
MainWindowContext.Get.AddSequence(message.SendTime, message.Data);
|
||||
byte frequency = message.Data[0];
|
||||
MainWindowContext.Get.AddSequence(message.SendTime, frequency, message.Data.Skip(1).ToArray());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -35,13 +35,13 @@ namespace SerialMonitor
|
||||
OnPropertyChanged("ConsoleText");
|
||||
}
|
||||
|
||||
public double SampleDelay { get { return 0.000026; } }
|
||||
public int MaxSequenceSize { get { return 2048; } }
|
||||
|
||||
private class Sequence
|
||||
{
|
||||
public ulong StartTime { get; set; }
|
||||
public ulong StartTime { get; set; } // time in microseconds of the first sample
|
||||
public byte[] Data { get; set; }
|
||||
public double Frequency { get; set; } // sampling rate (in samples per second)
|
||||
|
||||
public class Comparer : IComparer<Sequence>
|
||||
{
|
||||
@ -67,7 +67,8 @@ namespace SerialMonitor
|
||||
foreach (var sequence in Sequences)
|
||||
{
|
||||
double seqStartTime = (double)sequence.StartTime/1000000.0;
|
||||
if (seqStartTime + (double)sequence.Data.Length * SampleDelay > ViewportStartTime && seqStartTime < ViewportStartTime + ViewportTimeWidth)
|
||||
double sampleDelay = 1.0 / sequence.Frequency;
|
||||
if (seqStartTime + (double)sequence.Data.Length * sampleDelay > ViewportStartTime && seqStartTime < ViewportStartTime + ViewportTimeWidth)
|
||||
{
|
||||
foreach (var line in ConvertToLines(sequence))
|
||||
yield return line;
|
||||
@ -82,6 +83,7 @@ namespace SerialMonitor
|
||||
double scale = viewportWidth / ViewportTimeWidth; // in pixels per second
|
||||
|
||||
ulong displayStartTime = (ulong)(viewportStartTime_ * 1000000.0);
|
||||
double sampleDelay = 1.0 / sequence.Frequency;
|
||||
|
||||
double pos = ((double)sequence.StartTime - (double)displayStartTime) / 1000000.0 * scale;
|
||||
if (pos > 1000)
|
||||
@ -94,7 +96,7 @@ namespace SerialMonitor
|
||||
for (int idx = 1; idx < sequence.Data.Length; ++idx)
|
||||
{
|
||||
byte value = sequence.Data[idx];
|
||||
pos += SampleDelay * scale;
|
||||
pos += sampleDelay * scale;
|
||||
if (value > maxValue) maxValue = value;
|
||||
if (value < minValue) minValue = value;
|
||||
|
||||
@ -110,7 +112,7 @@ namespace SerialMonitor
|
||||
prevPos = pos;
|
||||
line.X2 = pos;
|
||||
|
||||
double time = (double)sequence.StartTime / 1000000.0 + (double)idx * SampleDelay;
|
||||
double time = (double)sequence.StartTime / 1000000.0 + (double)idx * sampleDelay;
|
||||
double lastHeight = ValueToHeight(time, value);
|
||||
|
||||
if (idx == prevIdx + 1)
|
||||
@ -142,10 +144,20 @@ namespace SerialMonitor
|
||||
}
|
||||
}
|
||||
|
||||
public void AddSequence(ulong startTime, byte[] data)
|
||||
public void AddSequence(ulong startTime, byte frequency, byte[] data)
|
||||
{
|
||||
// TODO: merge sequences if total size is lower than MaxSequenceSize
|
||||
var sequence = new Sequence { StartTime = startTime, Data = data };
|
||||
double cpuClock = 16000000.0;
|
||||
int adsp0 = (frequency & (1 << 0)) != 0 ? 1 : 0;
|
||||
int adsp1 = (frequency & (1 << 1)) != 0 ? 1 : 0;
|
||||
int adsp2 = (frequency & (1 << 2)) != 0 ? 1 : 0;
|
||||
int skipBit0 = (frequency & (1 << 3)) != 0 ? 1 : 0;
|
||||
int skipBit1 = (frequency & (1 << 4)) != 0 ? 1 : 0;
|
||||
int skipBit2 = (frequency & (1 << 5)) != 0 ? 1 : 0;
|
||||
int adcDivider = 1 << Math.Max(1, adsp0 + adsp1*2 + adsp2*4);
|
||||
int skip = skipBit0 + skipBit1 * 2 + skipBit2 * 4;
|
||||
double freq = cpuClock / (double)adcDivider / 13.0 / (double)(1 + skip);
|
||||
var sequence = new Sequence { StartTime = startTime, Frequency = freq, Data = data };
|
||||
Sequences.Add(sequence);
|
||||
OnPropertyChanged("Oscilloscope");
|
||||
OnPropertyChanged("MinTime");
|
||||
|
Loading…
Reference in New Issue
Block a user