I've been playing with getting an XBee to transmit whether a push button is up or down.
To do this I have the wire coming out of the circuit connected to DIO4 on the XBee. I used X-CTU to set DIO4 to digital input mode. Nothing else is enabled.
Now, the sensor XBee is transmitting a ZigBee I/O Data Sample Rx Indicator packet. I used the 'Building Wireless Sensor Networks' book to help parse out the packet. It says a packet always includes the analog sample values and will only include the digital ones if a digital pin is configured. I'm getting a 21 byte packet back, which implies the digital bit sample is not included. The digital mask says IO4 is enabled, and all the analog inputs are disabled. However, it appears the digital values were placed into the analog samples.
This is my confusion. Why is the digital sample being stuffed into the analog sample? Or is the analog sample simply left out if no analog inputs are configured (contrary to what the book says)?
Short answer: Yes, there are only analog samples in the payload if bits are set in the analog channel mask.
Long answer:
The XBee S2B documentation describes the details of the packet in the ZigBee IO Data Sample Rx Indicator section on page 114.
In summary, the payload starts with the number of samples (always 0x01), then a 16-bit digital channel mask and an 8-bit analog channel mask. The masks indicate what data follows. If any bits were set in the digital channel mask, there will be a 16-bit value holding the digital samples. Then a 16-bit value for each analog sample indicated in the analog channel mask, from AD0 to AD3, followed by the supply voltage.
Digi's Open Source XBee Host C Library has some code in include/xbee/io.h and src/xbee/xbee_io.c that demonstrate parsing of those frames.
Related
I've been working on a project where I use a PGA2310 volume control IC to set the volume of an audio signal. The chip's interface is supposedly SPI, but no matter how much I try, I just can't seem to get it right. The chip takes a 16 bit word over SPI that contains the left and right channel volume information.
I'm wondering if I am using the sdk all wrong and my code is whacked.
I guess my question is: Am I setting up and using the SPI functions correctly?
Here is my code
/**
* SPI interface for PGA2310 volume control ic
*/
#include "pico/stdlib.h"
#include "hardware/spi.h"
#include "pico/time.h"
const int CS = 0;
const int SDI = 1;
const int SCLK = 2;
const int LED_PIN16 = 16;
const int LED_PIN25 = 25;
uint16_t PGA2310();
uint16_t PGA2310() {
int baud = 1600000;
// SPI inistalization
spi_init(spi0, baud);
spi_set_format(spi0, 16, SPI_CPOL_0 , SPI_CPHA_0, SPI_MSB_FIRST);
// Sets SPI pins
gpio_set_function(CS, GPIO_FUNC_SPI);
gpio_set_function(SDI, GPIO_FUNC_SPI);
gpio_set_function(SCLK, GPIO_FUNC_SPI);
// Sets LED pins
gpio_init(LED_PIN16);
gpio_set_dir(LED_PIN16, GPIO_OUT);
gpio_init(LED_PIN25);
gpio_set_dir(LED_PIN25, GPIO_OUT);
// Data to send to chip. only sending first 8 bits for right channel.
// This is because I am currently just testing the output of the right channel
uint16_t high = 255;
uint16_t low = 100;
// Test by toggling between high and low volume states with LED indicators
while (true) {
gpio_put(LED_PIN25, 1);
spi_write16_blocking(spi0, &high, 1);
sleep_ms(2000);
gpio_put(LED_PIN25, 0);
spi_write16_blocking(spi0, &low, 1);
sleep_ms(2000);
}
}
I've tried a bunch of different methods that I found online for using SPI with the pico SDK. I've tried just sending 8 bits.
Let me know if more info is needed.
As explained in comments, SPI normally consists of 4 signals: /SS, SCLK, MOSI and MISO.
/SS = slave select, also known as chip select. Almost always active low.
SCLK = serial clock.
MOSI = Master Output Slave Input. The main data line. Your MCU seems to call this SDO (serial data out?).
MISO = Master Input Slave Output. Optional signal for duplex (two way) communication SPI. Your MCU seems to call this SDI (serial data input).
In this case the MCU is the master so you should be using MOSI/SDO. A MCU is almost always the master, except when communicating with other MCUs.
Additionally, always double check which CPOL and CPHA settings that the slave expects. Getting these wrong is a classic problem and can lead to subtle "clock skew" problems where everything works fine most of the time, then fail and give corrupt data intermittently.
The names you pick for variables/constants in C code do not have any effect on the hardware and they disappear as soon as the code is compiled. The most important thing is that you understand how the hardware works, read the documentation for the RP2040 SDK functions you are calling, and then pass the correct values to the RP2040 SDK functions.
The biggest problem is that you need to rethink every pin assignment. The RP2040 hardware SPI pin functions are defined in column F1 of the "GPIO Functions" section of the RP2040 datasheet. Here is an excerpt from that table:
This table tells us, for example, you cannot use pin 0 as the SPI0 CS function. If you assign that pin to be an SPI pin, it will be the SPI0 RX (data receiving) pin.
At a minimum, you need to pick one pin to be the SPI0 SCK pin and another to be the SPI0 TX pin, and you must connect those pins from the RP2040 to the equivalent pins on your device. Then you might also need to pick an RP2040 pin to control the CS pin on your device, if it has one. On the RP2040 side, this pin would be configured as a GPIO output pin and you would drive it low or high to enable your device. Refer to your device's datasheet for details about what signals it expects on its inputs and then use an oscilloscope to make sure you are generating compliant signals.
Another problem is that the spi_write16_blocking is probably modifying your high and low variables, so you will probably need to set those to the right values before each time that you use them. (So there is no point in having two different variables like that, just have one.)
I have been using ESP32 and writing code in Arduino. However, when I enable Bluetooth, GPIO4 and GPIO15 does not work to read analog inputs. I have connected IR LED's on both pins and reading analog signals. If Bluetooth code is not used, ESP32 is reading the analog signals and displaying it on serial monitor. If the below Bluetooth code is used, the reading is shown as 255 on both pins (reading 5v. Yes, they are 5v for now and will be level shifted to 3.3v).
Can someone please check and suggest a solution?
I have switched the sensors, removed them and whatever I do, the reading is the same when Bluetooth is read
Bluetooth code:
void init_bluetooth() {
ESP_BT.begin("EKA Robot"); //Name of your Bluetooth Signal
Serial.println("Bluetooth Device is Ready to Pair");
}
IR code:
// Read Infrared LED on GPIO4. Similar function exists to read GPIO15
int readIR() {
int sensorValue = analogRead(oaPinL);
delay(5);
sensorValue = map(sensorValue, 0, 4095, 0, 255);
return (sensorValue);
}
I expect to read the sensor values. However, all it shows is 255. Does it mean it is somehow pulled high?
There are two A/D converters in the ESP32 chip, ADC1 and ADC2. ADC2 pins can not be used when Wi-Fi or Bluetooth is used. Pins connected to ADC1 do work. These are GPIO32-36 and GPIO39.
I'm attempting to interface an STM32F303 Nucleo with an AD7748-4 ADC. Datasheet for the ADC:
https://www.analog.com/media/en/technical-documentation/data-sheets/ad7768-7768-4.pdf
The issue is, the ADC DOES NOT output the converted value through the SPI port, but rather employs a Data Ready Signal (DRDY), a Data Clock (DCLK), and a combination of 4 Data Outputs (DOUT0-DOUT3). The output streams 96 bits serially through one wire if I set it up that way, but timing is critical in my application and I need to clock the data in using DOUT0 to DOUT2, which would each output 32 bits. If I were serially streaming the data, I could trick the SPI port into reading it, but I'm not. The ADC is running at 20MHz, so DCLK will be operating at the same frequency. The Nucleo runs at a maximum of 72MHz, but when the DAM is utilized, it sets the clock to 64MHz.
In the STM manual, it describes a "GPIO port input data register (GPIOx_IDR) (x = A..H)" as being a read only register - my understanding is that the lower 16 bits can store an inputted value up to 16 bits (most likely for memory data R/W) - so the question is, how can I configure the GPIO to read in the data? I'm at a slight impass here. My instinct tells me that the Nucleo may not be fast enough to read the data coming from the ADC... Any ideas? All being written in C/C++ basically bare metal... I'm new to the Nucleo, haven't written code in 4 years - pardon any lapse in knowledge...
If DCLK works at 20Mhz, the uC is obviously not fast enough (you have about 3 instructions between each cycle, so even assembly language would be difficult to implement...). As I am not familiar with the stm architecture, I can only suggest a trick that will maybe spark some ideas in your head. Rather than using a crystal for the ADC, use a timer from the STM that is connected to an output pin, and clock the ADC using that pin (MCLK). When configuring the ADC using spi, idle mode, etc. you can leave this clock signal at 20Mhz. But when you need a sample from the ADC, stop the STM timer and clock the ADC "manually". (you practically control the DCLK signal). After your conversion routine is over, restart the timer at 20Mhz.
XBee has digital and analog pins.
Before hooking two XBees on API mode on radio, we want to first confirm the analog values from the sensor in order to range for scaling it to engineering value of the sensor. (E.g. scaling 0-65535 to say -20 - +40 deg C).
Is there a way we could check the pin status/values? We couldn't find this capability in XCTU software (or may be we don't know where it is).
Is it possible to see these values on serial port of XBee in computer (e.g. Raspberry pi)?
Yes, you can read serial data from remote xbee by connecting coordinator xbee(at PC) to its TX to DIN and RX to DOUT. That is for arduino uno. Then on serial, it will print 24 packets of data and digital data will be on 20 and 21 and analog data will be on 22 and 23.
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?