I'm trying to do something really simple and I'm having a bit of trouble getting it to work. I'm working with the MPL3115A2 Altitude/Pressure Sensor and a pic32 uC32 board, and I'm trying to communicate between the two using I2C. (uC32 board is similar enough to arduino that it's practically the same in terms of coding).
I'm using the wire library and I'm simply trying to read register 0x0C from the MPL3115A2, which should give me the device ID.
Here's a code snippet (the define is at the top of the code and the rest is in the main loop):
#define barAddress 0x60
Wire.beginTransmission(barAddress);
Wire.send(0x0C);
Wire.endTransmission();
Wire.requestFrom(barAddress, 1);
uint8_t a = Wire.receive();
Serial.println(a, HEX);
So I start the transmission with address 0x60 (From the datasheet: The standard 7-bit I2C slave address is 0x60 or 1100000. 8-bit read is 0xC1, 8-bit write is 0xC0.). Then I send 0x0C because that's the register I want to access. I then end transmission, and request 1 byte from address 0x60, receive that bit into a 8-bit variable, then print it.
The problem I run into is that when I print it, I just get 0. I don't get the device ID, just 0. No matter what register I try to read, I get 0.
I've been banging my head against a wall for the past few days trying to get this to work. I've attached something I've captured with a logic analyzer, as well as a list of registers from the datasheet of the MPL3115A2 that I've been trying to access.
Using a logic analyzer I can see the clock and data lines. The clock seems normal and the data line gives me the following:
START
Write['192'] + ACK
'12' + ACK
STOP
START
Read['193'] + ACK
'0' + NAK
STOP
This all seems correct to me (192 and 193 come from 8-bit write and read being 0xC0 and 0xC1), except for the '0'. I should be getting the device ID, not 0.
Thanks for any help with this!
You should look at Freescale's app note AN4481, which is referred to by the datasheet. Page 5 shows the single-byte read operation which is what you are doing, except that the register address write must not be followed by a STOP but instead uses a REPEATED-START.
I'm not familiar with the Wire library but it look like all you need to do is remove the Wire.endTransmission(); between the send and requestFrom.
Hopefully, this will solve your problem.
Related
I bought STEVAL-MKSBOX1V1 of ST and wanted to write my own library to create a BLE application.
The BLE module on board is SPBTLE-1S which mounts BlueNRG-1, I wrote my own firmware in order to communicate using SPI protocol.
After resetting the module using the pin I send a read request from MCU to the BLE module,
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port,SPI1_CS_Pin,0);
HAL_SPI_TransmitReceive(&hspi2,tx,rx,5,1);
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port,SPI1_CS_Pin,1);
I send:
{0x0b,0x00,0x00,0x00,0x00}
I get:
{0xff,0x08,0x00,0x06,0x00}
So apparently nothing good because the first byte is 0xff and not 0x02 (right?), but the 4th bit(0x06) should indicate the amount of data inside the read buffer.
If I read 6 bytes I get
{0x04,0xff,0x03,0x01,0x00,0x01}
And according to AN4494 It is exactly what I should read after the reset event on the module.
Then my question is why I keep getting {0xff,0x08,0x00,0x06,0x00} and not something like {0x02,....}?
Is there anything related to BlueNRG1 that is different from BlueNRG2? (It is so hard to find good documentation)
If anyone has some experience on SPI communication with this module I would like to have a bit of consulting.
Thanks in advance
{0xff,..} would be correct.
AN4494 is for BlueNRG-MS, the 5-byte SPI header for MISO is: {Ready, WBufLen, 0x00, RBufLen, 0x00}. In BlueNRG-1 and BlueNRG-2, that SPI header has been modified to: {0xff, CmdLen0, CmdLen1, DataLen0, DataLen1}, in order to support ACI packets with length more than 127 bytes in a single SPI transaction. The first byte in the header is fixed to 0xff.
Unfortunately currently there is no document describing the modification. You may need to refer to DTM SPI sample project to know the details.
In your transaction, if executing a Read command and continuing to read MISO for the 6 byte data:
{0xff,0x08,0x00,0x06,0x00},{0x04,0xff,0x03,0x01,0x00,0x01}
That is a ACI Blue initialized event, saying firmware has started properly. That can be parsed:
Header
0x0006: 6 bytes (data) is available to be read
Data
0x04: HCI event packet
0xFF: ACI (vendor specific) event
0x03: parameter length
0x10 0x00: event = 0x0001, which is ACI_BLUE_INITIALIZED_EVENT
0x01: reason code = 1, which means firmware started properly
This is driving me nuts for a couple of days now, so maybe you guys can give me some insights into what is going wrong.
I'm trying to read some data from an EEPROM (24LC16B) with an STM32(F0), but it just doesn't let me. I've tried an Arduino, which worked and does still work, so I do know that the wiring is correct.
This is my function to read the EEPROM data. (It is cut down to the very basis, just for testing): (Pastebin of my I2C_setup function)
uint16_t readEEPROMData(uint16_t deviceAddress, int memAddress){
// Wait while I2C peripheral is not ready
I2C_WaitForFlag(I2C_ISR_BUSY);
// Start I2C write transfer for 2 bytes, do not end transfer (SoftEnd_Mode)
I2C_TransferHandling(I2C1, 0xA2, 2, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
I2C_WaitForFlag(I2C_ISR_TXIS);
// For testing purpose, be sure to generate a stop command...
I2C_TransferHandling(I2C1, 0xA2, 0, I2C_AutoEnd_Mode, I2C_Generate_Stop);
return I2C_COMM_STATUS;
}
Here's an pastebin of the Arduino library I used.
I've used a logic analyzer to see how the communication is going, and now I really don't understand it. Here's a printscreen of the working Arduino version:
And here's a printscreen of the STM32 communication:
Logic analyzer exports (viewable with Saleae Logic)
As you can see, I'm using the same address (although I had to use 0xA2 with the STM32), and there are no weird things happening, besides the NACK. So what could possible be wrong?
Confirm if all bus timing requirement are satisfied.
Confirm if their is adequate delay after every write cycle (5 mS)
Confirm is bus capacitance falls under permissible limit of I2C (400 pF - Theoretically).
Confirm if the correct VCC is supplied
As mentioned by you are interfacing EEPROM with MCU using cable you need to conform on capacitance.
You can use an oscilloscope to check if their are any distortion in waveform. You can use a LCR meter to check the capacitance.
Try reducing bus speed 25kHz to 50 kHz and check waveform.
Try increasing the strength of pull resister.
The problem with the wrong VCC capacity (4.2v instead of 5v for example) is, that the timing can be different to. (not fully verified, but it fixed the problem)
I am doing a class project involving an Arduino Uno and a Picaxe 14m2.
I am in the middle of attempting to code a program for the Arduino Uno that will allow me to send and output value to the input on the Picaxe.
So in layman's, this is what I wish to achieve:
I want the Arduino to check a sensor, and if the sensor returns a specific value. (- I know this part, but not the next.) I then want the Arduino to send a value (HIGH, or 1 .. something like that) as an output to one of the Picaxe input pins. I then need the Picaxe to notice a value has been sent, and then do something else.
Any help would be appreciated.
Thanks.
If you are looking for that, you may want to specify what kind of PICAXE you have.
Since there is a difference in the types of these chips.
After that you may wanna look over the datasheet of the PICAXE so that you can find the instructions set and the type of program memory you have, "EEPROM....".
After that:
List your Is/Os, inputs and outputs.
Set your source code editor.
Write the source code and burn it to the PICAXE program
memory.(C, Assembly...)
Write your Arduino code, setting the Is/Os and telling the
Arduino how to deal with the signals in and out.(C language)
Make a circuit diagram for the hardware you are going to connect
between both chips.
Don't forget to see the loading effects on both the Arduino and
the PICAXE, because you don't want to burn your project hardware
after all.
Test your project and note that you will have to troubleshoot
both software and hardware whenever a problem occurs.
I suggest that you use the Oscilloscope to test the signals going in or coming out of both circuits + the sensor's signal.
For any extra thing you need the PICAXE to do, use If statements, because they are not so technical to implement and they are easy to write and troubleshoot.
For your scheme, you are actually making the Arduino give instructions to the PICAXE through a variable signal coming from a sensor.
^send me feedback and I will help more.
You will probably want to look into using UART (aka Serial) or i2c communication.
Serial communication should work with any PICAXE and Arduino, While i2c Will only work if you are using the X2 Series PICAXE Chips. i2c's main advantage is when using multiple slave devices (plus the master device, i.e. more than just 2 devices total) in which you can use the same two wires for up to around 128 devices. Serial (UART) communication is simpler, and only needs one wire (plus a common ground) to send data one way, it is what i'll show for the rest of this answer
Here is the manual entry for serial input for the PICAXE, and Here's the entry for serial output from the Arduino. The code you will need given your question will be something like the following:
For the arduino:
void setup(){
Serial.begin(9600);
}
void loop(){
if (conditionMet){ //whatever the condition is in your code
int bytesSent = Serial.write(“HIGH”); //send the string “HIGH"
}
}
and for the PICAXE:
main:
serin 6, T9600, ("HIGH") 'uses qualifier to look for exact message "HIGH"
'do whatever when criteria met
goto main
I have two Arduinos that I want to put in a wireless system to relay an IR code from a hand held remote in one room of the house, to a settop box located in another room. One Arduino has an IR decoder which decodes the key from a hand held remote, and sends it to the other Arduino parked in front of the box with an IR emitter. The system, in parts, works fine. When I get the code from the detector (to my PC) and send it manually (from my PC) to the emitting Arduino, it controls the box properly. But when I try to send the code wirelessly directly between the Arduinos, it doesn't work quite right. The commands do not appear to be relayed correctly and the emitting Arduino can't control the bx.
Here is what the decoding Arduino code looks like. "myNumber" holds the 4 byte key:
myNumber.UL = results->value;
Serial.write(&myNumber.B,4);
When the decoder detects the IR pattern, it posts the following to the Serial port whether I use the emitter or depress the on/off key on the remote. The key in question is 61A0F00F (power on/off):
Hex Field ASCII
0000 0F F0 A0 61 ...a
The decoder puts out this same response when I direct the actual remote towards the detector, or when I am driving my emitter with the code 61A0F00F. So it can't tell the difference between the actual remote and the Arduino-driven emitter. The problem is that this output is not understood correctly by the Arduino on the emitting end of the system.
Here is what the emitting code looks like:
void loop() {
int x = 0;
while (x < 4) {
if (Serial.available()) myNumber.B[x++] = Serial.read();
}
Serial.print(myNumber.UL, HEX);
if (x==3) irsend.sendNEC(myNumber.UL, 32); //drive IR emitter with NEC code
delay(10000);
And the serial output looks like this:
HEX field ASCII Field
0000 36 31 41 30 46 30 30 46 61A0F00F
When I put this hex code in manually, i.e. via CoolTerm, inverted (so 0FF0A061) the settop box responds (by turning on). When I link the Arduinos wirelessly, it does not.
Can anyone see what is wrong with the communication above? The numbers in the hex fields don't look quite right, the hex field from the decoder does look like hex, but the hex field from the emitter looks like ASCII? So is the emitter expecting an ASCII number but getting hex instead? I would have thought that the Serial.read and Serial. write would work the same way.
This is highly frustrating, as it appears that the system almost, almost works, BUT NOT QUITE!!
Any help/insight would be appreciated.
First a disclaimer: I haven't coded my arduino for several years.
At first glance it would appear you are being bitten by a conversion bug. I see a lot of conversions from byte to long etc. The key here would be to break things down to their simplest level and verify each level works.
First off I would verify the number of bytes being sent by checking the return value from Serial.write is indeed 4. Something as simple as flashing an led if Serial.write returns 4.
On the receiving end I think I would use ReadBytesUntil as this seems to be designed to do what you want and builds in some error checking (time outs and only 4 bytes).
I hope this helps. If not follow the golden rule: when in doubt - post more code!
Hope the late response helps.
The output data from the emitting end is correct. In your case, myNumber.UL = 0x61A0F00F. When executing the code "Serial.print(myNumber.UL, HEX);", the print class actually sent out the char sequence as '6''1''A''0''F''0''0''F'. So in your serial monitor the ACII data is "61A0F00F", and the corresponding HEX data is "36 31 41 30 46 30 30 46". You are confused about transferring data via text and binary format.
The problem of your code is at line "if (x==3) irsend.sendNEC(myNumber.UL, 32);". After receiving the four bytes data, the x is 4 other than 3. Changing the condition x==3 to be x==4 can fix your issue.
i have a problem with pic18f452 and uart
i use simplest code like that:
UART1_Init(9600); // Initialize UART module at 9600 bps
Delay_ms(100); // Wait for UART module to stabilize
and between forever while loop i have this code
UART1_Write_Text("HELLO2");
Delay_ms(1000);
also i have in my hardware lcd module it works very fine but my received data on pc
is a scrap like that
???m
i have checked all connection sothand time nothing wrong also i have changed MAX232 ic but with no luck ?!
my hardware is like that
finall all my connections are ok (polarity and every thing else ?)
EDIT : i use mikroc as a compiler
Looks like a baud rate error. Have you checked that your oscillator settings are resulting in the expected frequency? Does the serial library you are using expect a certain clock frequency and you are sure that you are running at that frequency, or does it work over a set of frequencies and you have correctly informed the serial library what frequency you are using? Also it would be useful to see the byte received as a decimal or hex number rather than just ASCII.
What about the start bits, number of data bits, parity, and stop bits? Are they the same on both ends?
It happens when you have loose connections i.e. from max 232 to Pic & from max 232 to PC.
Try checking the fluctuations over the transmit pin or usr Oscilloscope to see the ASCII values of Hello World alphabets.