Serial Acquisition#
[1]:
import os
import sys
sys.path.insert(0, os.path.realpath('../'))
[2]:
import LDAQ
[3]:
# Create serial acquisition source:
acq_serial = LDAQ.serial_communication.SerialAcquisition(port="COM3", baudrate=250000,
acquisition_name="arduino",
byte_sequence=(("int16", 2), ),
start_bytes= b"\xfa\xfb",
end_bytes= b"\n",
sample_rate=500,
channel_names=["channel 1", "channel 2"])
# Here the arduino sends out bytes over serial where a line would look like this:
# b"\xfa\xfb\x00\x01\x00\x02\n
# Explanation:
# b"\xfa\xfb" are the start bytes
# b"\n" is the end byte
# b"\x00\x01" is the first sample (int16)
# b"\x00\x02" is the second sample (int16)
[4]:
# Each acquisition source can also be run by itself:
acq_serial.run_acquisition(5.0) # run for 2 seconds
acq_serial.get_measurement_dict() # get the measurement dictionary
[4]:
{'time': array([0.000e+00, 2.000e-03, 4.000e-03, ..., 4.994e+00, 4.996e+00,
4.998e+00]),
'channel_names': ['channel 1', 'channel 2'],
'data': array([[512., 906.],
[512., 944.],
[512., 975.],
...,
[512., 758.],
[512., 812.],
[512., 862.]]),
'sample_rate': 500}
[5]:
# create core object and add acquisition source:
ldaq = LDAQ.Core(acquisitions=[acq_serial])
# set trigger:
ldaq.set_trigger(
source="arduino",
channel="channel 2",
level=100,
duration=5.0)
# run acquisition:
ldaq.run()
+--------+-------------------------------------------------+
| HOTKEY | DESCRIPTION |
+--------+-------------------------------------------------+
| s | Start the measurement manually (ignore trigger) |
+--------+-------------------------------------------------+
| q | Stop the measurement |
+--------+-------------------------------------------------+
Waiting for trigger...
triggered.
Recording...Measurement finished.
sys:1: ResourceWarning: Unclosed socket <zmq.Socket(zmq.PUSH) at 0x19d60157ee0>
ResourceWarning: Enable tracemalloc to get the object allocation traceback
[6]:
# Retrieve the measurement data:
measurement = ldaq.get_measurement_dict()
measurement
[6]:
{'arduino': {'time': array([0.000e+00, 2.000e-03, 4.000e-03, ..., 4.994e+00, 4.996e+00,
4.998e+00]),
'channel_names': ['channel 1', 'channel 2'],
'data': array([[ 512., 576.],
[ 512., 639.],
[ 512., 700.],
...,
[-512., 384.],
[-512., 447.],
[ 512., 512.]]),
'sample_rate': 500}}
C code uploaded to the Arduino:#
#include <avr/interrupt.h>
#include <stdint.h>
#include <math.h>
const uint16_t sampleRate = 500; // Set the desired sample rate in Hz
// Signal generation parameters:
const float frequencySquareWave = 5; // Frequency of the square wave in Hz
const float frequencySinWave = 10; // Frequency of the sinusoidal wave in Hz
const float amplitudeSinWave = 512; // Amplitude of the sinusoidal wave
const float offsetSinWave = 512; // Offset for the sinusoidal wave
// variables:
int16_t valSquareWave = 0;
int16_t valSinWave = 0;
// Other variables setup:
uint32_t sampleCounter = 0;
void setup() {
Serial.begin(250000); // Begin serial, set baudrate
setupTimerInterrupt();
}
void loop() {
// Do nothing in the main loop, everything is done by the interrupt
}
void setupTimerInterrupt() {
// Configure Timer1 for the desired sample rate
cli(); // Disable interrupts
TCCR1A = 0; // Clear control registers
TCCR1B = 0;
TCNT1 = 0; // Initialize counter value to 0
uint32_t ocrValue = (F_CPU / 8 / sampleRate) - 1; // Calculate OCR1A value
OCR1A = ocrValue; // Set compare match register for the desired sample rate
TCCR1B |= (1 << WGM12); // Set CTC mode
TCCR1B |= (1 << CS11); // Set 8 prescaler
TIMSK1 |= (1 << OCIE1A); // Enable timer compare interrupt
sei(); // Enable interrupts
}
ISR(TIMER1_COMPA_vect) {
// Timer interrupt routine
float elapsedTime = (float)sampleCounter / sampleRate;
sampleCounter++;
// Generate square wave
valSquareWave = (int16_t)(512 * (sin(2 * PI * frequencySquareWave * elapsedTime) >= 0 ? 1 : -1));
// Generate sinusoidal wave
valSinWave = (int16_t)(amplitudeSinWave * sin(2 * PI * frequencySinWave * elapsedTime) + offsetSinWave);
Serial.write(0xfa); // starting byte 1
Serial.write(0xfb); // starting byte 2
send2Bytes(valSquareWave);
send2Bytes(valSinWave);
Serial.write('\n'); // ending byte
}
// Functions for sending data over serial:
void send4Bytes(uint32_t data) {
Serial.write(data & 0xFF);
Serial.write((data >> 8) & 0xFF);
Serial.write((data >> 16) & 0xFF);
Serial.write((data >> 24) & 0xFF);
}
void send2Bytes(int16_t data) {
Serial.write(data & 0xFF);
Serial.write((data >> 8) & 0xFF);
}
void send1Byte(int8_t data) {
Serial.write(data & 0xFF);
}