Freescale Pressure Sensor MPL3115A2 I2C communication with Arduino - arduino

Does anyone have experience with the MPL3115A2 Freescale I2C pressure sensor?
I need to use it in a project concerning Arduino UNO r3, but I can't get communication between them correctly. Here is my code:
#include <Wire.h>
void setup(){
Serial.begin(9600);
/*Start communication */
Wire.begin();
// Put sensor as in Standby mode
Wire.beginTransmission((byte)0x60); //0x60 is sensor address
Wire.write((byte)0x26); //ctrl_reg
Wire.write((byte)0x00); //reset_reg
Wire.endTransmission();
delay(10);
// start sensor as Barometer Active
Wire.beginTransmission((byte)0x60);
Wire.write((byte)0x26); //ctrl_reg
Wire.write((byte)0x01); //start sensor as barometer
Wire.endTransmission();
delay(10);
}
void getdata(byte *a, byte *b, byte *c){
Wire.beginTransmission(0x60);
Wire.write((byte)0x01); // Data_PMSB_reg address
Wire.endTransmission(); //Stop transmission
Wire.requestFrom(0x60, 3); // "please send me the contents of your first three registers"
while(Wire.available()==0);
*a = Wire.read(); // first received byte stored here
*b = Wire.read(); // second received byte stored here
*c = Wire.read(); // third received byte stored here
}
void loop(){
byte aa,bb,cc;
getdata(&aa,&bb,&cc);
Serial.println(aa,HEX); //print aa for example
Serial.println(bb,HEX); //print bb for example
Serial.println(cc,HEX); //print cc for example
delay(5000);
}
The data I receive is : 05FB9 (for example). When I change the register address (see Wire.write((byte)0x01); // Data_PMSB_reg address), I expect the data to change, but it doesn't! Can you explain this to me?
You can find the documentation and datasheets on the NXP website.
I can't properly understand how they communicate with each other. I got communication between Arduino and some other I2C sensors with same communication protocol without any problem.

Your problem is likely due to the fact that the Freescale part requires Repeated-Start I2C communication to do reads. The original Arduino two-wire library (TWI library used by Wire), did not support Repeated-Start.
I know this because I had to rewrite TWI for one of my projects to support Repeated-Start (interrupt driven, both Master and Slave). Unfortunately I've never gotten around to uploading my code, but someone else did essentially the same thing here (at least for Master which is what you need):
http://dsscircuits.com/articles/arduino-i2c-master-library.html
Lose the Wire library and use their I2C library instead.

Related

How can i use SPI on Arduino Due to communicate with AD7124-8 correctly

I want to read data from AD7124-8 with arduino Due via SPI. I found several libraries, but i dont get anything back from my ADC modul. By using an Oscilloscope i made sure my Arduino sends data via MOSI, SCK and CS work aswell. Just the MISO dataline doesnt get me anything back.
I first used this library (https://github.com/NHBSystems/NHB_AD7124), but decided to use a much easier Code to just make sure everything is working fine. I tried to to talk to the communication register to get the ID of my device from the ID register. You can find the registers on page 39 of the datasheet :https://www.analog.com/en/products/ad7124-8.html .
Im sending 0x00 and 0x05 to get back the 0x14 which should be the correct ID. Just zeros arriving (shown by Osci).
I found a solution in a Forum, but im not sure about why it differs with the data sheet:
https://ez.analog.com/data_converters/precision_adcs/f/q-a/24046/ad7124-8-for-arduino-due
when i use it the code stops running at the Line: value[0] = SPI.transfer(0x00);
They send 0x40 at the beginning, too.
Here my simple Code:
#include <SPI.h>
// Physical Pins
const int csPin = 10;
int value[7] {0};
void setup() {
Serial.begin (9600);
pinMode(10,OUTPUT);
SPI.begin(10);
SPI.setClockDivider(10, 128);
SPI.setDataMode(SPI_MODE3);
}
void loop() {
digitalWrite(csPin, LOW);
//SPI.transfer(csPin, 0x00);
SPI.transfer(csPin,0x00,SPI_CONTINUE); //Tell Communication Register you are going to read ID register
SPI.transfer(csPin,0x05);
//SPI.transfer(csPin,0x00); //Get data from Communication Register
delay(1);
digitalWrite(csPin, HIGH);
delay(1);
Serial.print(value[0],HEX);
}
I hope someone can help me out.
Greetings
First of all, this may not related to your question, but you are using old SPI methods setClockDivider(), setDataMode(), and setBitOrder() that has been deprecated since 2014. It is recommend to use use transactional SPI APIs which I have some explanation here.
Secondly, according to datasheet page 85, to access the ID register, you send one-byte to specific which register that you need to communicate with. Your code send two bytes, 0x00 and 0x05, which is incorrect.
Furthermore, based on page 78 of the datasheet, in order to read a register, bit 6 need to be set to 1 for a read operation, and 0 for a write operation.
Try the following code:
#include <SPI.h>
#define READ_REGISTER 0B01000000 // bit 6 set to 1 for read operation
#define ID_REGISTER 0x05
const int csPin = 10;
void setup() {
Serial.begin (9600);
digitalWrite(csPin, HIGH); // set csPin to HIGH to prevent false trigger
pinMode(csPin,OUTPUT);
SPI.begin();
}
void loop() {
SPI.beginTransaction(SPISettings(84000000/128, MSBFIRST, SPI_MODE3));
digitalWrite(csPin, LOW);
SPI.transfer(READ_REGISTER | ID_REGISTER); // read register 5
uint8_t id = SPI.transfer(0x00); // get the id
digitalWrite(csPin, HIGH);
SPI.endTransaction();
Serial.print(id,HEX);
}

SPI Arduino Interface with Absolute Encoder

I am trying to retrieve data from an RLS absolute rotary encoder via SPI through Arduino Uno. I have managed to learn the basics of SPI, but I can't seem to get this working. I keep printing the transfer data and keep getting 255.
I also use the recommended pins for Arduino Uno here: https://www.arduino.cc/en/reference/SPI
Here is the link to the Absolute Encoder DataSheet: https://resources.renishaw.com/en/details/data-sheet-orbis-true-absolute-rotary-encoder--97180
Any help is appreciated.
Here is my code I have been trying:
#include <SPI.h>
unsigned int data;
int CS = 10; //Slave Select Pin
// The SS pin starts communication when pulled low and stops when high
void setup() {
Serial.begin(9600);
RTC_init();
}
int RTC_init() {
pinMode(CS, OUTPUT);
SPI.begin();
SPI.setBitOrder(LSBFIRST); // Sets Bit order according to data sheet (LSBFIRST)
SPI.setDataMode(SPI_MODE2); // 2 or 3, Not sure (I have tried both)
digitalWrite(CS, LOW); // Start communications
/*
Commands List:
Command "1" (0x31) – position request (total: 3 bytes) + 4 for multi-turn
Command "3" (0x33) – short position request (total: 2 bytes) + 4 for multi-turn
Command "d" (0x64) – position request + detailed status (total: 4 bytes) + 4 for multi-turn
Command "t" (0x74) – position request + temperature (total: 5 bytes) + 4 for multi-turn
Command "v" (0x76) – serial number (total: 7 bytes)
*/
unsigned int data = SPI.transfer(0x33); // Data
digitalWrite(CS, HIGH); // End communications
return(data);
}
void loop() {
Serial.println(RTC_init());
}
First, you forgot to set your CS pin to output. That won't help.
void setup()
{
Serial.begin(9600);
digitalWrite(CS, HIGH); // set CS pin HIGH
pinMode(CS, OUTPUT); // then enable output.
}
SPI is a two way master/slave synchronous link, with the clock being driven by bytes being sent out by the master. This means that when transacting on SPI, you are expected to send out as many bytes as you want to receive.
As shown on the timing diagram on page 14 of the datasheet, you are expected to send one byte with the command, then as many null bytes as the response requires minus 1.
The diagram shows the clock being low at idle, and input bits being stable when the clock goes low, that's SPI mode 1.
To read the position, for a non-multiturn encoder.
unsigned int readEncoderPos()
{
// this initialization could be moved to setup(), if you do not use
// the SPI to communicate with another peripheral.
// Setting speed to 1MHz, but the encoder can probably do better
// than that. When having communication issues, start slow, then set
// final speed when everything works.
SPI.beginTransaction(SPISettings(1'000'000, MSBFIRST, SPI_MODE1));
digitalWrite(CS, LOW);
// wait at least 2.5us, as per datasheet.
delayMicroseconds(3);
unsigned int reading = SPI.transfer16(0x3300); // 0x3300, since we're sending MSB first.
digitalWrite(CS, HIGH);
// not needed if you moved SPI.beginTransaction() to setup.
SPI.endTransaction();
// shift out the 2 status bits
return reading >> 2;
}

How to read XBee RSSI in API mode?

I am trying to test a XBee RSSI in API mode at receiving end, how can I retrieve the RSSI value of the receiving radio in arduino.
I configured both XBee in API-2 mode and are connected to arduino by pin 4-5(rxtx & txrx) to Xbee radios.
Sending frame code is like below and there is no problem in transmission at both ends,
uint8_t data[] = {'H','i'};
XBeeAddress64 addr64 = XBeeAddress64();
addr64.setMsb(0x00000000); // Msb address of receiver
addr64.setLsb(0x00000000); // Lsb address of receiver
ZBTxRequest zbTx = ZBTxRequest(addr64, data, sizeof(data));
xbee.send(zbTx);
delay(1000);
At the receiving end I tried pulseIn of arduino and .getRssi() of , The former function gives "0" in result while the later gives "102" but remains the same as I move the Xbee radios away from each other.
What should I need to do for getting correct RSSI at the receiving end..?
Hopefully this answer helps you and others.
Assuming you are using the following lib:
https://github.com/andrewrapp/xbee-arduino
and you have a series 1 module you can use the following test code for quick diagnostics. the commented parts can of course also be used if needed
#include <XBee.h>
#include <SoftwareSerial.h>
// XBee's DOUT (TX) is connected to pin 8 (Arduino's Software RX)
// XBee's DIN (RX) is connected to pin 9 (Arduino's Software TX)
SoftwareSerial serial1(8, 9); // RX, TX
XBee xbee = XBee();
XBeeResponse response = XBeeResponse();
Rx16Response rx16 = Rx16Response();
Rx64Response rx64 = Rx64Response();
// uint8_t xbeeOption = 0;
// uint8_t xbeeData = 0;
uint8_t xbeeRssi = 0;
void setup() {
Serial.begin(9600);
serial1.begin(9600);
xbee.setSerial(serial1);
}
void loop() {
xbee.readPacket(100);
if (xbee.getResponse().isAvailable()) {
Serial.println("Xbee available");
if (xbee.getResponse().getApiId() == RX_64_RESPONSE || xbee.getResponse().getApiId() == RX_16_RESPONSE) {
Serial.println("64 or 16");
if (xbee.getResponse().getApiId() == RX_16_RESPONSE) {
Serial.println("16");
xbee.getResponse().getRx16Response(rx16);
// xbeeOption = rx16.getOption();
//Serial.print("xbeeOption: "); Serial.println(xbeeOption);
//xbeeData = rx16.getData(0);
//Serial.print("xbeeData: "); Serial.println(xbeeData);
xbeeRssi = rx16.getRssi();
Serial.print("xbeeRssi: "); Serial.println(xbeeRssi);
}
else {
Serial.println("64");
xbee.getResponse().getRx64Response(rx64);
//xbeeOption = rx64.getOption();
//Serial.print("xbeeOption: "); Serial.println(xbeeOption);
//xbeeData = rx64.getData(0);
//Serial.print("xbeeData: "); Serial.println(xbeeData);
xbeeRssi = rx64.getRssi();
Serial.print("xbeeRssi: "); Serial.println(xbeeRssi);
}
}
}
If you use a series2 module there is only the way using the hardware pwm signal: In order for the RSSI pwm signal to be updated it needs to have received an API packet. Also, for the series 2 Xbee this applies only for the last hop of the packet, so from last router to destination. You need to use the XBee rssi pin and some coding depending on your appliance.
The rssi for distance is not very reliable and you will see a change perhaps every 10 to 15 meters while sending packets. So just moving a Xbee around on your workplace will not change the values.
EDIT:
When using a series 2 module there is the following possibility: connect the rssi pin of the xbee (6) to an Arduino pwm pin (eg 10) and measure the incoming signal, which could then be mapped to a quality or/and distance range. So writing your own rssi function. The usual xbee libs only support series1 modules.

MeetAndroid with SoftwareSerial issue

I use Amarino with SoftwareSerial (from here: http://www.double-oops.org/mini-blog/amarinowithsoftwareserial ) but I have a strange issue.
It seems that there are some strange behaviour in the MeetAndroid Library. In order to receive events I had to make this changes:
in init() I had to change
ack = 19;
with
ack = 226;
because this is the char I received from the phone at the end of a message
and in receive() I had to change
uint8_t lastByte;
with
char lastByte;
otherwise the
if(lastByte == ack)
won't be true ever
Does anyone have any idea why I had this problems? Why do i get another ack char and why is the if not working for char (ack) and uint8_t (lastByte)
This is my sketch:
/*
Receives Test Events from your phone.
After it gets a test message the led 13 will blink
for one second.
*/
#include <MeetAndroid.h>
#include <SoftwareSerial.h>
MeetAndroid meetAndroid(4, 2, 115200);
int onboardLed = 13;
void setup()
{
meetAndroid.registerFunction(testEvent, 'A');
pinMode(onboardLed, OUTPUT);
digitalWrite(onboardLed, HIGH);
}
void loop()
{
meetAndroid.receive(); // you need to keep this in your loop() to receive events
}
void testEvent(byte flag, byte numOfValues)
{
flushLed(300);
flushLed(300);
}
void flushLed(int time)
{
digitalWrite(onboardLed, LOW);
delay(time);
digitalWrite(onboardLed, HIGH);
delay(time);
}
I found the problem, it is baudrate related. When using software serial I have to use a lower baudrate (9600 for example), otherwise when receiving multiple characters at once it won't work. And since amarino library sends multiple library at once (signaling the start and the end of the message for example) it caused problems when using software serial on slower hardware (like the Arduino Uno used by me). Probably with better hardware (Arduino Mega) changing the baudrate is not necessary.
Example for changing the baudrate is available here:
Receiving multiple chars at once with Software Serial
Long answered short:
When using SoftwareSerial on slower hardware use a low baudrate (like 9600). Also make sure to set the bluetooth board work on the lower baudrate.

I²C with energia and EK-TM4C1294XL

I want to communicate with a SHT21 Sensor from a EK-TM4C1294XL Board.
But it seems that I2C communication is quite difficult with energia.
I used different setups with external Pullup, used the internal pullup and also no pullup. then i tried both I2C interfaces by setting Wire.setModule(0) or Wire.setModule(1) but in all cases the result is that either everything freezes in the Wire.endTransmission() function or i receive only bytes filled with 0.
I basically used this library: https://github.com/elechouse/SHT21_Arduino and modified the example script like this:
#include <Wire.h>
#include <SHT2x.h>
void setup()
{
Wire.setModule(1); // SCL = PN_5 (pin 49), SDA = PN_4 (Pin 50)
Wire.begin();
// optional use this:
// pinMode(PN_5, INPUT_PULLUP);
// pinMode(PN_4, INPUT_PULLUP);
Serial.begin(115200);
}
void loop()
{
Serial.print("Humidity(%RH): ");
Serial.print(SHT2x.GetHumidity());
Serial.print(" Temperature(C): ");
Serial.println(SHT2x.GetTemperature());
delay(1000);
}
There is a boosterpack containing the SHT21 as well, but i did not found any sample code for that... I did not managed yet to get the C stuff running on my linux machine, probably I2C is broken in the energia lib?
Edit: it seems that there is a bug in the library too. The timing must be precise and also 3 bytes are requested and only 2 read. when reading the last byte i do not get good values but at least the loop does not freeze.

Resources