C code to Read data from nonin Pulse Oximeter device via bluetooth Serial Port profile in linux - c

I am trying to communicate to the Nonin Pulse oximeter device to read the data (Pulse rate and SPO2 level) via Bluetooth. Nonin device supports SPP and HDP profile. I want to communicate through SPP profile. I am able to scan and pair with the device by the sample code available in Bluez.
Please tell me next steps how to send command and read data from the device. I have got struck at this point.

I realize this is a late response, but I recently setup data acquisition from a Nonin PalmSAT 2500A VET unit. I am using the RTC-1000 cable and an RS232 to USB converter.
This is straight from the manual:
"Information from the device, in the real-time mode, is sent in an ASCII serial format at 9600 baud with 9 data bits, 1 start bit, and 1 stop bit. The data are output at a rate of once per second.
NOTE: The 9th data bit is used for odd parity in memory playback mode. In real-time mode, it is always set to the mark condition. Therefore the real-time data may be read as 8 data bits, no parity.
Real-time data may be printed or displayed by devices other than the pulse oximeter. On power up a header is sent identifying the format and the time and date. Thereafter, the data are sent once per second in the following format:
SPO2=XXX HR=YYY
where “XXX” represents the SpO2 value, and “YYY” represents the pulse rate. The SpO2 and pulse rate will be displayed as “---” if there are no data available for the data reading."
Link to manual:
http://www.proactmedical.co.uk/proshop_support_docs/2500aman.pdf
What model oximeter are you working with?

Related

Implementing an SSI slave interface on STM32 Board

I am trying to implement a SSI Slave Protocol on a STM32 Board. Since the STM32 Boards don't have a SSI interface, I used its SPI interface in Slave(Transmit only mode). The master SSI sends 24 clock signals and the slave reacts by sending its data(3 Bytes) over the MISO pins. The problem I am facing is that the data is always shifted on the left on every clock signal coming from the master. For example assuming I am constantly sending 0x010101 from slave.
At first transmission the master receives 0x010101
At Second transmission the master receives 0x020202
At third transmission the master receives 0x040404
Can someone please give me some hints on how to solve this problem?
The data-shift with each transmission can happen when the SPI slave recognizes an (unexpected) additional clock pulse. Looking at the SSI protocol description on Wikipedia this actually makes sense:
In order to transmit N bits of data the master emits N clock cycles, followed by another clock pulse to signal the end of the transfer (so-called "Monoflop Time" - referring to the original hardware implementation of the SSI interface). Since the SPI protocol / SPI slave does not know about this additional clock pulse, it begins to output the first bit of the next data byte, which is in turn not recognized by the SSI master. As a result this leads to a shift in the data bits recognized by the SSI master on the next SSI frame.
Unfortunately, it is not easy to handle the Monoflop time correctly with the SPI slave. In order to deal with the additional clock pulse, we could try to set the SPI frame size to 25 bits on the slave side. Since the STM32 hardware only supports SPI frame sizes between 4 bit and 16 bit, the only choice is to set it to 5 bit. This is not very convenient, since we need to convert the 3 byte (24 bit) output data into 5 blocks of 5 bit (24 bit output data + 1 bit dummy data), but it should work for a "normal" transfer.
Things get more complicated though, if we also want to handle the cases "Multiple transmissions" and "Interrupting transmission" correctly. We need to monitor the clock signal to be able to detect the monoflop timeout. This can be done using a STM32 hardware timer with an external trigger. When the timer expires, we need to reset the SPI unit (in order to handle an interrupted transmission) and update the output value. This "simple" task can be quite challenging since it requires a couple of instructions - requiring a fast MCU depending on the SSI clock frequency.
Alternatively the SSI protocol can be implemented using a software-only "bit banging" solution. But this requires a fast MCU as well in order to handle a fast SSI clock correctly.
IMHO the best solution is to use a small (inexpensive) FPGA to implement the SSI slave and let the MCU feed it with data over a traditional SPI interface.

Log data from MPU6050 through serial (UART) fails (data loss)

here is the problem I am facing. I have interfaced my ATmega328P with a 6-axis IMU (MPU6050 with the GY521 breakout board). I can read data through the TWI interface (Atmel's I2C) and send it to my PC (running Ubuntu) via the UART. I am using custom-built libraries for both these communication protocols, but they are pretty standard and seem to work just fine. The goal of the project is to compute orientation data from the IMU readings in real-time, say at 100 Hz.
The main problem is that I cannot log data from the device at 100 Hz (not even at 50 Hz). The orientation filter I am using (here) requires a quite high frequency and 100 Hz turned out to work fine (tested offline acquiring data from another device).
Right now, I am using the 16-bit timer of the ATmega328P to sample data at 100 Hz and this seem to work, as I have added to the ISR a line to toggle the built-in LED and it looks to me that it is blinking at 100 Hz (I can barely see it turning on and off). In the same ISR, I read the values from the inertial sensor and, just to log them, send these values through the serial port. Every 10 ms (maximum), I send 9 floats (36 bytes) with a baud rate of 115200. If I use the Arduino IDE's Serial Monitor to visualize this data stream, I notice something very weird, as in the following screenshot.
https://imgur.com/zTBdkhv
As you notice taking a look at the timestamps, there is a common 33 ms delay every 2 or 3 sets of samples received. Moreover, I get roughly the 60% of the data. For example, an acquisition of 10 seconds only gets me less than 600 samples (per each variable) instead of 1000. Moreover, I tested the same sending only one variable through the UART (i.e. only a single float, 4 bytes) and this results in the same behavior!
By the way, I am exploiting the following to send each byte (char) via the UART interface.
void writeCharUART(char c) {
loop_until_bit_is_set(UCSR0A, UDRE0);
UDR0 = c;
}
Even though my ISR runs at 100 Hz (LED blinking seem to confirm that), data loss may occur at the level of the TWI transmission. To prove that, I modified the code of the ISR to send just a normal char (T) instead of data from the MPU and I got a similar behavior. Something like this:
00:10:05.203 -> T
00:10:05.203 -> T
00:10:05.236 -> T
00:10:05.236 -> T
00:10:05.236 -> T
00:10:05.236 -> T
00:10:05.269 -> T
So, I guess there is something wrong with the UART library and I actually sample at 100 Hz, but the logging frequency is much lower (and not constant). How can I solve this issue and/or debug the UART library? Do you see other reasons to justify this issue?
EDIT 1
As pointed out in the comments, it seems to be a problem of the receiving software that limits the frequency to ~30 Hz by some sort of buffering. To confirm that, I programmed the ATmega328P with the following code (this time using the IDE).
void loop() {
Serial.println("T");
}
At first, I thought there was no delay this time, but I could find it after 208 samples. So, there are ~200 samples received at the same timestamp and another bunch of samples after 33 ms. This may be proof that the receiving software introduces this delay.
I also tested a simple serial monitor that I had developed in C and, even though there is no timestamp functionality, I am also loosing samples if I fix the duration of the acquisition sampling at 100 Hz. My serial monitor is based on the termios.h library, but I could not find any documentation about its way of buffering incoming data.
There are two issues here:
You are missing messages. You checked the sample rate just with your eyes and told us that you can still see a very fast blinking. Depending on the colour of your LED, the ambient light, your physical state, and your eyes this could mean anything from 30 Hz to 100 Hz.
I would not trust my eyes to estimate and rather use an oscilloscope or a frequency counter to measure.
You could reduce the frequency of the LED blinking to 1Hz or even lower by dividing in software. Such a low frequency can be measured by hand via a stop watch. For example count 30 blinks and check the time needed for this.
Add a counter to the message and increment it with each message. You will see it right away if you're losing data.
The timestamps seem to indicate that the messages are "clustered" at about 30 Hz.
I'm guessing that the source of the timestamp in running at 30 Hz. So it can not give you more accurate values.
I kind of solved my issues! First of all, thanks to the comments I have checked that my ISR was correctly running at 100 Hz. Doing so, I could be sure that the problem where somewhere else, namely in the UART communication.
I found this very helpful: Linux, serial port, non-buffering mode
Apparently, the Serial Monitor provided by the Arduino IDE uses exploits the termios.h library and uses its default settings. I checked also the user manual and switched to the polling-read mode. Quoting from the user manual
If data is available, read(2) returns immediately, with the lesser of the number of bytes available, or the number of bytes requested. If no data is available, read(2) returns 0.
Hence, I switched back to my serial monitor code and changed the initPort() function adding the following lines of code.
struct termios options;
(...)
options.c_cc[VTIME] = 0;
options.c_cc[VMIN] = 0;
I noticed right away a much higher data frequency in the terminal. I kept the 1 Hz LED blinking in the ISR and there is no period stretching. Moreover, an acquisition of 10 seconds this time gave me roughly 1000 samples per variable, consistent with a sampling rate of 100 Hz.
On the AVR side, I also changed the way I send data through the UART. Before, I was sending 9 floats like this:
sprintf(buffer, "%f, %f, %f", value1_x, value1_y, value1_z);
serial_print(buffer); // no "\n" sent here
sprintf(buffer, "%f, %f, %f", value2_x, value2_y, value2_z);
serial_print(buffer); // again, no "\n" sent
sprintf(buffer, "%f, %f, %f", roll, pitch, yaw);
serial_println(buffer); // "\n" is sent here once the last data byte is sent
Now, I replaced all this with a single call to the function serial_println() and I write only 6 floats to the buffer.

How does the LPC1788FBD144 chip configure the ADC function to collect two signals simultaneously?

Now I need to configure the AD sampling feature of the LPC1788FBD144 chip, which requires the ability to read both signals simultaneously. However, there is only one ADC in the chip, how to sample two signals. By looking at the chip manual, you know that the chip has an ADC mouth with 8 channels at the same time. But in software mode, only one channel can be sampled at a time. If in the hardware scan mode, which bits of the 8 channels are set to 1, the sampling values of these channels can be read. I suspect that you may need to configure a hardware scan mode to sample both signals simultaneously.
My question is:
1、LPC1788FBD144 chip has only one ADC mouth, how to sample two signals simultaneously?
2、The first 8 bits in the AD control register of LPC1788FBD144 chip are the selection and input channels. In the software mode, only one can be set to 1. In the hardware scan mode, any value containing 1-8 can be written into that bit. I now need to collect two signals, which will require two channels, so two channels must be configured in the hardware scan mode. So what is the hardware scan pattern? How to start the hardware scan mode?
LPC1788FBD144 chip has only one ADC mouth, how to sample two signals simultaneously?
You can't read them exactly at the same time. Microcontroller SA ADC:s work by connecting one pin at a time to the actual ADC. How fast it can do this depends on sample rate and ADC clock. According to the product brief of that part, it has a conversion rate of up to 400kHz, meaning you'll get at best a 2.5us delay between samples. Check the manual for details.
This is usually good enough for the vast majority of applications. If you have tighter real-time requirements than that, you should probably be using a DSP instead of some general-purpose microcontroller.
You could of course get a MCU with two ADC:s, or use an external ADC. But I kind of doubt that your real-time specification "read at exactly the same time" makes sense. What is the purpose of the ADC read?
As for how to use your specific ADC, I don't know, but typically you'd set it up for "continuous conversion", where it keeps cycling through the channels you have enabled and write the results to their corresponding data input registers.

Troubleshooting Missing Data Sample Packets in xBee?

I have my first two nodes setup, I have a ZigBee Coordinator API module and a ZigBee End Device API module. I have the end point connected on Analog pins 1-3 with sensors for temp, moisture, and light.
I have the pins D1-3 configured for ADC, and the IR sample rate setting at EA60 for once per 60 seconds.
The frames log on the co-ordinator shows a stream of Explicit RX Indicator frames and Transmit Status frames, but I am seeing no IO Data Sample RX Indicator frames.
Also, I wired an LED to the sleep indicator pin, and it is almost constantly lit, it's certainly not sleeping for a minute at a time.
Any help would be greatly appreciated.
Do the Explicit RX Indicator frames look like they might contain your I/O samples? You might need to set ATAO=0 to receive the 0x92 frame type, but you're probably better off sticking with parsing the Explicit Rx to find the I/O sample payload and using that.
Regarding your sleeping end device, have you configured the various XBee registers to have it sleep? Find the section on sleep in your XBee documentation and read through it entirely -- there are many configuration options. For the ZigBee specification, you'll need to wake up every 7 seconds, even if it's just a short wakeup for the device to ping its parent device and check for network messages.
Finally, make sure you've wired your LED correctly. If the sleep indicator pin is active low, it will be pulled low whenever sleeping. And the end device will be waking for a short amount of time, possibly too short to see on an LED. You could use a scope or a logic analyzer to monitor the pin for changes instead.

Need some help on Serial Port Transmission

i'm currently using DS89C450 MCU on Keil C51 Programming.
I have an Infrared Receiver attached to P3^2 which is the falling edge trigger. Whenever I press a key on the remote control, it will trigger the interrupt and save it into the xdata X or Y (bit by bit then byte by byte for 500 bytes).
I'm trying to transmit the data bit (either '1' or '0') from the buffer to the hyperterminal via Serial Port. However, I do not get any data displayed when I press the remote control.
Can anyone expert tell me why and how do i get it to work?
The program is here:
http://pastebin.com/hpAw2ipH
Google "Terminal by br#y", it can show serial comms in HEX. Most UARTs cannot send a single bit, rather they will send a character of N bits, usually 7 or 8, with start/stop/parity bits (8-bits, no parity, 1 stop bit being the universal default). It can make life easier to encode data as ASCII, perhaps even with start/stop characters, so you know when you're getting real data.
For even more detail, use an oscilloscope, BusPirate or LogicSniffer (from DangerousPrototypes.com) to sniff the communications data.

Resources