Print Oxygen Saturation with Arduino - arduino-c++

#include <Wire.h>
#include "MAX30100_PulseOximeter.h"
#define REPORTING_PERIOD_MS 1000
// PulseOximeter is the higher level interface to the sensor
// it offers:
// * beat detection reporting
// * heart rate calculation
// * SpO2 (oxidation level) calculation
PulseOximeter pox;
uint32_t tsLastReport = 0;
// Callback (registered below) fired when a pulse is detected
void onBeatDetected()
{
Serial.println("Beat!");
}
void setup()
{
Serial.begin(115200);
Serial.print("Initializing pulse oximeter..");
// Initialize the PulseOximeter instance
// Failures are generally due to an improper I2C wiring, missing power supply
// or wrong target chip
if (!pox.begin()) {
Serial.println("FAILED");
for(;;);
} else {
Serial.println("SUCCESS");
}
// The default current for the IR LED is 50mA and it could be changed
// by uncommenting the following line. Check MAX30100_Registers.h for all the
// available options.
// pox.setIRLedCurrent(MAX30100_LED_CURR_7_6MA);
// Register a callback for the beat detection
pox.setOnBeatDetectedCallback(onBeatDetected);
}
void loop()
{
// Make sure to call update as fast as possible
pox.update();
// Asynchronously dump heart rate and oxidation levels to the serial
// For both, a value of 0 means "invalid"
if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
Serial.print("Heart rate:");
Serial.print(pox.getHeartRate());
Serial.print("bpm / SpO2:");
Serial.print(pox.getSpO2());
Serial.println("%");
tsLastReport = millis();
}
}
I want to output oxygen saturation with Arduino.
If you run it and turn on the serial monitor, only the Initializing pulse oximeter works, and no data is transmitted after that.
I want to output the values ​​of oxygen saturation and pulse received from the sensor once per second on the serial monitor.

Related

How to optimize the code for reading SPI through ARDUINO in SLAVE mode

Not important:
I am doing a project to integrate a bluetooth module into a car radio pioneer. I understand perfectly well that it's easier to buy a new one =) but it's not interesting. At the moment, the byproduct was an adapter on arduino of resistor buttons, which the pioneer did not understand. The same adapter also controls the bluetooth board, it can switch the track forward and backward (there is no button on the steering wheel for pause). Now I want the bluetooth to turn on only in AUX mode. But there is a problem, which mode can be understood only by reading the signal from the SPI bus of the commutation microcircuit. I was able to read this data using arduino nano. I do not have an analyzer, but it is not necessary that I would understand something additional with it.
Essence of the question:
Using the scientific poke method, I found sequences indicating the launch of a particular mode, for example:
10110011
1
111
1000000
I'm sure I'm doing it wrong, but in the meantime I get duplicate results. But, when I try to detect them using IF, the nano speed is not enough and the chip starts to pass data.
#include "SPI.h"
bool flag01, flag02, flag03, flag11, flag12, flag13, flag31, flag32, flag33;
void setup (void)
{
Serial.begin(9600);
pinMode(MISO, OUTPUT);
SPCR |= _BV(SPE);
SPI.attachInterrupt();
}
// Вызываем функцию обработки прерываний по вектору SPI
// STC - Serial Transfer Comlete
ISR(SPI_STC_vect)
{
// Получаем байт из регистра данных SPI
byte c = SPDR;
Serial.println(c, BIN);
if (c == 0b1) {
Serial.println("1 ok");
flag11 = true;
} else {
flag11 = false;
}
if (c == 0b11 && flag11) {
Serial.println("11 ok");
flag12 = true;
} else {
flag12 = false;
flag11 = false;
}
if (c == 0b1100000 && flag11 && flag12) {
Serial.println("1100000 ok");
flag13 = true;
} else {
flag13 = false;
flag12 = false;
flag11 = false;
}
}
void loop(void)
{}
I myself am scared to look at this code, but I cannot think of anything better. It seems like I heard about some kind of buffer, but I don't know how to screw it to this solution. After all, the data packets go with dropping the CS signal and I can’t figure out how to determine the beginning and end of the packet from the commands in order to write it to a buffer or array and only then go through it with a comparison.
I will be grateful if someone will tell me at least in which direction to move.
There is also esp8266, but there is a limitation on the size of a data packet of 32 bits in a slave mode and I do not know how to get around it correctly.
So, actually the question.
How can I optimize the code so that the arduino has time to process the data and I can catch the pattern?
Perhaps, if we implement reading of data of arbitrary length on esp8266, or at least fill them to the required length, it would help me. But I still can't figure it out with the spi.slave library.
First you should keep your ISR as short as possible, certainly don't use Serial print inside the ISR.
Secondly, if you don't know exactly how long the data is, then you need to have a buffer to capture the data and try to determine the data length first before you trying to analysis it.
volatile uint8_t byteCount = 0;
volatile bool dataReady = false;
byte data[32];
// SPI interrupt routine
ISR (SPI_STC_vect)
{
data[byteCount++] = SPDR;
dataReady = true;
}
void setup (void)
{
// your SPI and Serial setup code
}
void loop (void)
{
// for determine the data stream length
if (dataReady) {
Serial.println(byteCount);
dataReady = false;
}
}
Once you know how long the data stream is (let assumed it is 15-byte long), you can then change your sketch slightly to capture the data and analysis it.
volatile uint8_t byteCount = 0;
volatile bool dataReady = false;
byte data[32];
// SPI interrupt routine
ISR (SPI_STC_vect)
{
data[byteCount++] = SPDR;
if (byteCount == 15)
dataReady = true;
}
void loop (void)
{
if (dataReady) {
dataReady = false;
// do your analysis here
}
}

Using performance monitor unit to generate an interrupt on Xilinx ZynqZC706

I am currently trying to use the performance monitor to generate an interrupt when an overflow of Data Cache misses occurs. I have enabled the pmu and the IRQ for the performance monitor (PMINTENSET is 1 for the counter). I am able to see that the overflow flag is set when the overflow occurs but the interrupt is never triggered. I think I am missing something when setting up the interrupt. I am using Xilinx SDK 2018.2.
I have attached my code for setting up the interrupt:
XScuGic xInterruptController; /* Interrupt controller instance */
static void setup_interrupt(void)
{
uint32_t status;
XScuGic_Config *pxGICConfig;
pxGICConfig = XScuGic_LookupConfig( XPAR_SCUGIC_0_DEVICE_ID );
if (pxGICConfig==NULL)
{
xil_printf("\nERROR LOOKING UP CONFIGURATION");
for(;;);
}
status = XScuGic_CfgInitialize( &xInterruptController, pxGICConfig, pxGICConfig->CpuBaseAddress );
if (status != XST_SUCCESS)
{
xil_printf("\nERROR INITIALIZING CONFIGURATION");
for(;;);
}
status = XScuGic_SelfTest(&xInterruptController);
if (status != XST_SUCCESS)
{
xil_printf("\nERROR: SELF TEST FAILURE");
for(;;);
}
/*
* Initialize the exception table.
*/
Xil_ExceptionInit();
status = RegisterInterruptExceptions(&xInterruptController);
if (status != XST_SUCCESS) {
xil_printf("\nERROR: SetUP Interrupt System Failed");
for(;;);
}
status = XScuGic_Connect( &xInterruptController, XPS_PMU0_INT_ID, (Xil_ExceptionHandler) pmuIRQ_handler, ( void * ) &xInterruptController);
if (status!= XST_SUCCESS)
{
xil_printf("\nERROR CONNECTING INTERRUPT");
for(;;);
}
XScuGic_SetPriorityTriggerType(&xInterruptController, XPS_PMU0_INT_ID, 8, 0b10); // Priority 8 (second highest) and high level sensitivity
XScuGic_InterruptMaptoCpu(&xInterruptController, 0, XPS_PMU0_INT_ID);
// Enable the interrupt for the xTimer in the interrupt controller.
XScuGic_Enable( &xInterruptController, XPS_PMU0_INT_ID );
}
int RegisterInterruptExceptions(XScuGic *XScuGicInstancePtr)
{
/*
* Connect the interrupt controller interrupt handler to the hardware
* interrupt handling logic in the ARM processor.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler) XScuGic_InterruptHandler,XScuGicInstancePtr);
/*
* Enable interrupts in the ARM
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}
void pmuIRQ_handler( void *CallbackRef )
{
xil_printf("Interrupt occurred\n");
}
I am not sure if I need to use Vivado to map the PMU interrupt to the GIC? I couldn't find any examples on generating interrupts using the performance monitor. I am currently using the default ZC706 HW platform provided by Xilinx SDK and I am not sure if I need to generate a bitstream in Vivado the maps the PMU to the GIC? I thought that this was done by using XScuGic_InterruptMaptoCpu().
I tried with both XPS_PMU0_INT_ID and XPS_PMU1_INT_ID, but neither worked. I tried to follow this post on using shared peripheral interrupts since PMU is this type of interrupt: https://forums.xilinx.com/t5/Processor-System-Design-and-AXI/Using-Private-and-Shared-interrupts-on-Zynq/m-p/773673
Thanks for the help,
Javier
The last parameter is incorrect. It should be 0b01 For high-level sensitivity instead of 0b10, as shown below:
XScuGic_SetPriorityTriggerType(&xInterruptController, XPS_PMU0_INT_ID, 8, 0b01); // Priority 8 (second highest) and high level sensitivity

Arduino-GPS is not giving longitude and latitude values

I am trying to track the GPS but i am not able to receive my longitude and latitude data.
I am using "Adafruit Ultimate GPS Breakout V3" GPS module and "Arduino UNO R3"
Here is my code. I have tried both
:::First Code:::
#include <SoftwareSerial.h>
#include <TinyGPS.h>
long flat, flon;
SoftwareSerial gpsSerial(2, 3); // Create GPS pin connection
TinyGPS gps;
void setup(){
Serial.begin(9600); // connection serial
gpsSerial.begin(9600); // gps burd rate
}
void loop(){
while(gpsSerial.available()){ // check for gps data
if(gps.encode(gpsSerial.read())){ // encode gps data
gps.get_position(&flat, &flon); // get lattitude and longitude
// display position
Serial.print("Position: ");
Serial.print("lat: ");Serial.println(flat);
Serial.print("lon: ");Serial.println(flon);
}
}
}
:::Second Code:::
#include <SoftwareSerial.h>
#include <TinyGPS++.h>
#define RXPin 3
#define TXPin 4
#define GPSBaud 9600
#define ConsoleBaud 115200
// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);
// The TinyGPS++ object
TinyGPSPlus gps;
void setup(){
Serial.begin(ConsoleBaud);
ss.begin(GPSBaud);
Serial.println("GPS Example 2");
Serial.println("A simple tracker using TinyGPS++.");
Serial.println();
}
void loop(){
// If any characters have arrived from the GPS,
// send them to the TinyGPS++ object
while (ss.available() > 0)
gps.encode(ss.read());
// Let's display the new location and altitude
// whenever either of them have been updated.
if (gps.location.isUpdated() || gps.altitude.isUpdated()){
Serial.print("Location: ");
Serial.print(gps.location.lat(), 6);
Serial.print(",");
Serial.print(gps.location.lng(), 6);
Serial.print(" Altitude: ");
Serial.println(gps.altitude.meters());
}
}
Which pins are you using? The first code shows 2&3, but the second shows 3&4. And remember, the GPS TX pin goes to the Arduino RX pin. Likewise, the GPS RX pin goes to the Arduino TX pin. For the first code, the GPS TX pin should be connected to Arduino pin 2.
Are you inside? You probably have to be outside, or at least near some windows for the GPS device to receive from the satellites. It could take 15 minutes for the first fix to happen.
Although you don't show any output, you should try a simple echo program first, to see if the GPS device is sending anything.
#include <NeoSWSerial.h>
NeoSWSerial gpsSerial( 2, 3 );
void setup()
{
Serial.begin( 9600 );
gpsSerial.begin( 9600 );
}
void loop()
{
if (gpsSerial.available())
Serial.write( gpsSerial.read() );
}
I would also recommend getting the NeoSWSerial library. It's my library, and it's much more efficient and reliable than SoftwareSerial.

Cortex M-0: Simple external interrupt

I'm trying to set up an external interrupt on my LPC812 uC. I've made the following code
#include "LPC8xx.h"
#define RLED 7 // red LED
bool pause = false;
void PININT0_IRQHandler(void)
{
pause = !pause;
}
int main(void) {
LPC_GPIO_PORT->DIR0 |= 1<<RLED; // set pin as output
LPC_GPIO_PORT->SET0 = 1<<RLED;
NVIC_EnableIRQ(PININT0_IRQn);
while (1)
{
if(!pause)
{
LPC_GPIO_PORT->CLR0 = 1<<RLED;
}
}
}
But it isn't working. Am I missing something?
I'm not familiar with NXP MCUs.
But at least place break piont inside PININT0_IRQHandler, to understand clearly that interrupt is not generated.
Also it will be nice to clear interrupt flag inside handler.
Some peripherals need interrupt permission in peripheral registers in addition to NVIC setup.
Did you setup input pin somewhere?
Your code only initialize GPIO 7 pin as output.

GPS altitude print to LCD

I am trying to get my arduino uno to display the altitude from a GPS module, without any other data. I am still learning the code, but I've run into a problem where I can't seem to find what command is used to pull the altitude from the GPS string. I know it is pulling the data successfully, as I ran the example code from http://learn.parallax.com/kickstart/28500 and it read the first bit of the string, though I moved onto trying to get the altitude before getting it to scroll the whole string.
I am using a basic 16x2 LCD display, and the display I have working fine.
The end goal of this project is a GPS/gyroscope altimeter that can record to an SD card and record temperature, and deploy a parachute at apogee (15,000ft) and a larger parachute at 1,000ft.
Here is the code I am using for the altitude, I've marked the section I can't figure out. (probably just missing a term, or I might have really messed something up)
Any help would be appreciated, have a great day.
#include <SoftwareSerial.h>
#include "./TinyGPS.h" // Special version for 1.0
#include <LiquidCrystal.h>
TinyGPS gps;
SoftwareSerial nss(0, 255); // Yellow wire to pin 6
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
void gpsdump(TinyGPS &gps);
bool feedgps();
void setup() {
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// initialize the serial communications:
Serial.begin(9600);
Serial.begin(115200);
nss.begin(4800);
lcd.print("Reading GPS");
lcd.write(254); // move cursor to beginning of first line
lcd.write(128);
lcd.write(" "); // clear display
lcd.write(" ");
}
void loop() {
bool newdata = false;
unsigned long start = millis();
while (millis() - start < 5000) { // Update every 5 seconds
if (feedgps())
newdata = true;
}
gpsdump(gps);
}
// Get and process GPS data
void gpsdump(TinyGPS &gps) {
// problem area
float falt, flat, flon;
unsigned long age;
gps.f_get_position(&flat, &flon);
inline long altitude (return _altitude);
long _altitude
;lcd.print(_altitude, 4);
}//end problem area
// Feed data as it becomes available
bool feedgps() {
while (nss.available()) {
if (gps.encode(nss.read()))
return true;
}
return false;
}
lcd.print(x,4) prints base-4. Did you want that, or do you want ordinary base-10 (decimal)?
Secondly, where do you expect _altitude to come from? It's uninitialized. There's also an uninitialized falt, and a weird inline long altitude line which doesn't mean anything.
You might be better of learning C++ first, in a desktop environment. Debugging an embedded device is a lot harder, and you're still producing quite a few bugs.