I2C PROGRAMMING ON ARM - microcontroller

I'm unable to use I2C on an ARM CORTEX M3 process.
What am I doing wrong? Which test could I perform to find the problem?
It is a GD32F130C8 (master) and I'm programming it with KEIL (using the GD32F1x0 Firmware Library)
The slave is a MPU-6050 (accelorometer)
I defined the variable with local address and MPU-6050 device:
#define I2C_ACCELEROMETER_ADDRESS 0xD0 //( 0x68 + one bit)
#define I2C_OWN_ADDRESS 0x72
Then I initialized the I2C PIN this way:
//Init I2C communication to accelerometer
// enable I2C0 clock
rcu_periph_clock_enable(RCU_I2C0);
// connect PB8 to I2C0_SCL
gpio_af_set(GPIOB, GPIO_AF_1, GPIO_PIN_8);
// connect PB9 to I2C0_SDA
gpio_af_set(GPIOB, GPIO_AF_1, GPIO_PIN_9);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_8);
gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ,GPIO_PIN_8);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_9);
gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ,GPIO_PIN_9);
Then I initialized the I2C this way:
void I2C_Accelerometer_init(void){
// configure I2C0 clock
i2c_clock_config(I2C0, 100000, I2C_DTCY_2);
// configure I2C0 address
i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, I2C_OWN_ADDRESS);
// enable I2C0
i2c_enable(I2C0);
// enable acknowledge
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
}
Then periodically (each second) I try to get the data from the accelerometer.
There is no error but the variable "accelerometer_x_high" is always zero (this is basically my problem).
The following code is executed each second. As you can see I set power management to 0, then I request register with accelerometer data, then I try to get the data from the slave device:
extern uint8_t Accelerometer_X_High;
//periodically called by timers in it.c
void GetAccelerometerData(void){
uint8_t bytesToReadIndex=0;
//WAKE UP ACCELEROMETER (6B 00)
// wait until I2C bus is idle
while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY));
// send a start condition to I2C bus
i2c_start_on_bus(I2C0);
// wait until SBSEND bit is set
while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND));
// send slave address to I2C bus
i2c_master_addressing(I2C0, I2C_ACCELEROMETER_ADDRESS, I2C_TRANSMITTER);
// wait until ADDSEND bit is set
while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND));
// clear ADDSEND bit
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
// send a data byte
i2c_data_transmit(I2C0,0x6B); //PWR MANAGEMENT
// wait until the transmission data register is empty
while(!i2c_flag_get(I2C0, I2C_FLAG_TBE));
// send a data byte
i2c_data_transmit(I2C0,0x00); //WAKE UP
// wait until the transmission data register is empty
while(!i2c_flag_get(I2C0, I2C_FLAG_TBE));
// send a stop condition to I2C bus
i2c_stop_on_bus(I2C0);
while(I2C_CTL0(I2C0)&0x0200);
//REQUEST ACELEROMETER DATA (3B )
// wait until I2C bus is idle
while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY));
// send a start condition to I2C bus
i2c_start_on_bus(I2C0);
// wait until SBSEND bit is set
while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND));
// send slave address to I2C bus
i2c_master_addressing(I2C0, I2C_ACCELEROMETER_ADDRESS, I2C_TRANSMITTER);
// wait until ADDSEND bit is set
while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND));
// clear ADDSEND bit
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
// send a data byte
i2c_data_transmit(I2C0,0x3B); //ACCELEROMETER REGISTER
// wait until the transmission data register is empty
while(!i2c_flag_get(I2C0, I2C_FLAG_TBE));
// send a stop condition to I2C bus
i2c_stop_on_bus(I2C0);
while(I2C_CTL0(I2C0)&0x0200);
//now reopen the bus to receive the reply
// wait until I2C bus is idle
while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY));
// send a start condition to I2C bus
i2c_start_on_bus(I2C0);
// wait until SBSEND bit is set
while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND));
// send slave address to I2C bus
i2c_master_addressing(I2C0, I2C_ACCELEROMETER_ADDRESS, I2C_RECEIVER);
// wait until ADDSEND bit is set
while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND));
// if we receive only one byte: reset ACKEN bit
i2c_ack_config(I2C0, I2C_ACK_DISABLE);
//clear ADDSEND bit
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
// if we receive only one byte: send stop condition
i2c_stop_on_bus(I2C0);
/* wait until the RBNE bit is set */
while(!i2c_flag_get(I2C0, I2C_FLAG_RBNE));
//read a data from I2C_DATA
Accelerometer_X_High = i2c_data_receive(I2C0);
// if we receive more bytes: send a stop condition to I2C bus
//i2c_stop_on_bus(I2C0);
while(I2C_CTL0(I2C0)&0x0200);
// enable acknowledge
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
}
acquiring signals with oscilloscope I get the following result:
this is a screenshot with entire signal:
http://www.tr3ma.com/Dati/IMG_1526.JPG
On the signal there are also strange spikes:
http://www.tr3ma.com/Dati/spike1.JPG
http://www.tr3ma.com/Dati/spike2.JPG
http://www.tr3ma.com/Dati/spike3.JPG
http://www.tr3ma.com/Dati/spike4.JPG

It works. I created a loop to read all the registers and I was able to read the entire content of the chip. There is no error on the firmware. The only problem is that the chip is not the one that I supposed it to be. I have to find the right part number of accelerometer and find the register to wake it up.

Related

Can an I2C Eeprom have two addresses?

I own an EEPROM module with the P24C256 chip. (not AT24C256).
After scanning for available I2C devices, i got response from two devices.
Scanning...
I2C device found at address 0x50 !
I2C device found at address 0x58 !
done
I looked up the datasheet, but cannot find any additional information.
I thought that the device, has two banks for storage, but that does not seem to be the case.
How is this possible? After disconnecting the module, no I2C devices are reported.
#include <Wire.h>
void setup()
{
Wire.begin();
Serial.begin(9600);
while (!Serial); // Leonardo: wait for serial monitor
Serial.println("\nI2C Scanner");
}
void loop()
{
byte error, address;
int nDevices;
Serial.println("Scanning...");
nDevices = 0;
for(address = 1; address < 127; address++ )
{
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0)
{
Serial.print("I2C device found at address 0x");
if (address<16)
Serial.print("0");
Serial.print(address,HEX);
Serial.println(" !");
nDevices++;
}
else if (error==4)
{
Serial.print("Unknown error at address 0x");
if (address<16)
Serial.print("0");
Serial.println(address,HEX);
}
}
if (nDevices == 0)
Serial.println("No I2C devices found\n");
else
Serial.println("done\n");
delay(5000); // wait 5 seconds for next scan
}
Yes they can.
Depending on the size of the i2C EEPROM and how the memory blocks are organized you can have 2 or more device address. For example the ST24/25x04 EEPROM are 4 Kbit electrically erasable programmable memories, organized as 2 blocks of 256 x8 bits. That means that I2C gives you two device addresses (0x50 and 0x51 in the memory above), that will access each block with 1 byte address.
It might be the problem with the EEPROM address bits, in case they are in floating state and not connected properly, Could you please check the connections on those address bits? Try to connect them to the same ground as your micro-controller, but yes, as advised above, schematics is highly needed.
That behavior is not implied to by. The datasheet says the address should be only one (but its three lower bits can be chosen).
The schematics for the boards shows only two bits (A0, A1) are selected by the dip-switch, and A2 is tied to the ground.
I see no initialization in the code. What frequency the TWI bus is working at? Also, in the pictures of the module it has jumpers to pull-up resistors unsoldered, and it has 10kOhm pull-up resistors even if jumpers are soldered - that may be too high.
Probably you have issue just because the wire is not returned to the high level fast enough.
Check pull-up resistors are engaged (jumpers are soldered on the board)
Try to add additional pull-ups (about 4.7k) on SCL, SDA
Try to set lower frequency, e.g. Wire.setClock(50000);

XBee S2C and XBee S1 Pro communication

I have an XBee S1 Pro, which is configured as a coordinator. and an XBee S2C, which is configured as an end-node. Both are loaded with the 802.15.4 firmware. By using XCTU, I sent and received the data in Transparent mode.
I have now configured the end-node to API-1 mode and connected it to an Arduino Nano. I want to read the payload. Here is my Arduino code:
void setup() {
Serial.begin(9600);
Serial.println("Setup done...");
while (!Serial) {;}
}
void loop() {
if (Serial.available()) {
for (int i = 0; i < 8;i++) {
byte discard = Serial.read();
}
Serial.write(Serial.read());
Serial.print(",");
}
When I send 'hello' from the coordinator I get:
Setup done...
FFFFFFFF
,FFFFFFFF
,FFFFFFFF
,FFFFFFFF
,FFFFFFFF
,FFFFFFFF
,FFFFFFFF
,FFFFFFFF
,FFFFFFFF
,
Is there an easier way to do this like using the Arduino XBee library?
Could someone kindly help me?
Have you confirmed that the two XBee modules are joined to the same network? My understanding was that S1 was just 802.15.4, and S2 was ZigBee. You should probably start your project with identical networking hardware to eliminate that as a source of problems.
I'd recommend following a tutorial and using that code to establish a working starting point for any code you want to write.
Edit: adding some code
First off, you need to have two serial ports. One for your console where you can see the output of Serial.print() and the other for communicating with the XBee module.
Second, start with this loop:
void loop() {
// echo bytes received on XBee module to serial console
if (XBee.available()) {
Serial.write(XBee.read());
Serial.print(",");
}
// echo bytes received on serial console to XBee module
if (Serial.available()) {
XBee.write(Serial.read());
}
}
This way you're dumping every byte you receive, and only calling XBee.read() when there's data available to read.
You might want to keep your XBee module at 9600 baud, but increase your stdio interface (Serial) to 115200 since you're printing more than one character per byte received from the XBee module.

Why do sketches take up so much space and memory in arduino?

When I compile my program i get this message
Sketch uses 7,074 bytes (21%) of program storage space. Maximum is 32,256 bytes.
Global variables use 1,033 bytes (50%) of dynamic memory, leaving 1,015 bytes for local variables. Maximum is 2,048 bytes.
What do this message states?
this is my code
#include <SPI.h>
#include <MFRC522.h>
#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance.
void setup() {
Serial.begin(9600); // Initialize serial communications with the PC
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card
Serial.println("Scan PICC to see UID and type...");
}
void loop() {
// Look for new cards
if ( ! mfrc522.PICC_IsNewCardPresent()) {
return;//go to start of loop if there is no card present
}
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial()) {
return;//if ReadCardSerial returns 1, the "uid" struct (see MFRC522.h lines 238-45)) contains the ID of the read card.
}
// Dump debug info about the card. PICC_HaltA() is automatically called.
mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
}
and I'm getting this message on blinking led long pin 13 too
If you look at this question you'll see that without care, constant strings like "Scan PICC to see UID and type..." will use SRAM (dynamic memory) and not flash (program storage space).
It is a message that informs you on the state of arduino's memory.

master slave communication between two attiny 85 IC

Is it possible to communicate between two ATtiny85? I can use my Arduino to communicate with ATtiny85 by using Arduino Uno as the master and ATtiny85 as a slave. But I want to use one ATtiny85 as the master and one as a slave. Is this possible ?
I am not able to understand the examples given in TinyWireM library. I want a simple master and slave code for communication. For example, master should ask for 1 integer value and slave should reply.
My slave code :
#define I2C_SLAVE_ADDRESS 0x14 // Address of the slave
#include <TinyWireS.h>
int i=0;
void setup()
{
TinyWireS.begin(I2C_SLAVE_ADDRESS); // join i2c network
TinyWireS.onRequest(requestEvent);
}
void loop()
{
TinyWireS_stop_check();
}
void requestEvent()
{
if(i==1000)
{
TinyWireS.send(1);
i=0;
}
else
i++;
}
My master code
#include <TinyWireM.h>
#define DS1621_ADDR 0x14
void setup()
{
TinyWireM.begin();
pinMode(4, OUTPUT);
}
void loop()
{
TinyWireM.requestFrom(DS1621_ADDR,4); // Request 1 byte from slave
int tempC = TinyWireM.receive();
if(tempC)
{
digitalWrite(4, HIGH);
delay(1000); // wait for a second
digitalWrite(4, LOW);
delay(1000); // wait for a second
}
if(tempC>1)
{
digitalWrite(4, HIGH);
delay(1000); // wait for a second
digitalWrite(4, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
}
I tried the above code but still I cannot see the LED blinking. But if I keep slave code as it is and use the following master code on an Arduino then everything works fine.
Arduino Uno code as master.
#include <Wire.h>
float i1=-1, i2=-1;
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial for output
}
void loop()
{
Wire.requestFrom(4, 1); // request 1 byte from slave address 4
while(Wire.available()) // slave may send less than requested
{
i1 = Wire.read(); // receive a byte as character
Serial.println(i1); // print the character
}
}
connection is and connections are SDA to SCL pins
pin 5 of master attiny85 - pin 7 of slave attiny85
pin 7 of slave attiny85 - pin 5 of master attiny85
I also tried by no cross connecting them. example and connections are SDA to SDA pins
pin 5 of master attiny85 - pin 5 of slave attiny85
pin 7 of slave attiny85 - pin 7 of master attiny85
but still no success.
Yes, it is possible to use 1 ATtiny85 as a master, and another as a slave. The TinyWireM and TinyWireS libraries are both well-written and easy to use.
Handling a request and sending back bytes is as simple as setting the onRequest slave read event handler to a function of your choice that sends the correct data back. There are examples of this in the TinyWireS library.
Did you use the pull-up resistor for both, the SDA and SCL? They are important for the I2C protocol.
FYI: The logic '0' on the either bus is set by device driving actual '0' on the pin. On the other hand, the logic '1' is set on the bus by putting the device pin in the high impedance, in case on the ATtiny, it means setting pin into INPUT direction. When the both, the master and slave set pins to hiZ, the pull-up resistor pulls the voltage on the bus to value representing logic '1'. This solution allows avoiding contention on bi-directional bus (one device driving '1' and second driving '0') than can lead to short-circuit and damaging devices. So, if you don't use the pull-up resistor, the bus will be left floating whenever logic '1' is driven and it will lead to protocol errors.

Arduino 101 - BLE Queries: Characteristics and Advertisement

I have the following queries regarding BLE peripheral on Arduino 101 :
Is is possible to advertise any characteristic value(dynamic data) rather than the UUID in the advertising packet. If so what are the APIs for that? My goal is to get any temperature data in the adv packet instead of connecting to the peripheral.
Current Observation: I was only able to advertise service uuids and local name using the APIs setAdvertisedServiceUuid and setLocalName.
2.In the following code I was able to start and capture the advertisement in the first instance but in the letter instance the begin had a false return value. Am I doing anything wrong? The idea is to start and stop the advertisement and may be even change the advertisement data.
#include <CurieBle.h>
void setup() {
// set LED pin to output mode
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
//BLE Peripheral
BLEPeripheral * blePeripheral = new BLEPeripheral;
//Set the Local Name
blePeripheral->setLocalName("MyDevice");
//Start Advertising
blePeripheral->begin();
//Run the advertisement for 20 seconds
delay(20000);
//Stop the advertisement
blePeripheral->end();
//Delete the BLE Peripheral
delete blePeripheral;
//Wait 5 seconds before starting the next adv
delay(5000);
}
Any help will be appreciated.
Thanks.
Swaroop
BLEPeripheral blePeripheral; // BLE Peripheral Device (the board you're programming)
BLEService ledService("19B10000-E8F2-537E-4F6C-D104768A1214"); // BLE LED Service
// BLE LED Switch Characteristic - custom 128-bit UUID, read and writable by central
BLEUnsignedCharCharacteristic switchCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
https://www.arduino.cc/en/Reference/BLEPeripheralConstructor

Resources