Board: Udoo Neo Full OS: Udoobuntu 2.1.2 + UART6 patch Kernel: Linux udooneo 3.14.56-udooneo-02053-gcf9f3ed-dirty #3 SMP PREEMPT Thu Apr 13 16:43:23 UTC 2017 armv7l armv7l armv7l GNU/Linux Hi everyone, I'm facing a very annoying and tricky bug related to I2C and M4. I'm building a wather station with UDOO and BMP180 and a RTC DS3231. Both of them use I2C. If I plug them directly with my Udoo, everything works. I tested them separately today but I already know that they work together with a breadboard. I usually check them with i2cdetect and this is the BMP Code: udooer@udooneo:~$ sudo i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- 77 And this is the RCT: Code: udooer@udooneo:~$ sudo i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- 6f 70: -- -- -- -- -- -- -- -- udooer@udooneo:~$ sudo i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- udooer@udooneo:~$ sudo i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- 6f 70: -- -- -- -- -- -- -- -- Every i2cdetect commands lasted <2sec. Actually I'm wondering why it has 3 interfaces. I knew about 0x68 but what about 0x57, but above all, 0x6f discussed in HERE too. Btw, this is merely curiosity...let's go back to the problem. We designed a PCB for the Udoo and this is the design: The pcb gets 12V from the right, UDOO boots and the sensors are off by default. We put a transistor linked to GPIO3 to turn the sensors power on by: Code: pinMode(3, OUTPUT); digitalWrite(3, HIGH); //SENSORS on in the setup(). Everything works...but not always, and this is the tricky bug. Sometimes the sketch isn't able to get data from the I2C bus, so the RTC and BMP don't work. In this case I try to i2cdetect the bus, but this time, every 'i2cdetect -y 1' lasts 1sec per address. No problems with i2cdetect -y 0,2,3,4. Sometimes I get the sensors, sometimes not. Code: udooer@udooneo:~$ sudo i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- Any idea why? Any test I can do? Thank you!
From where are you normally monitoring the I2C, from Arduino side or Linux side? Did you switch off I2C from Linux side if monitored from Arduino? Didyou use wire or wire1 in Arduino sketch?
So, I get sensors data from Arduino side that writes them on Serial and I read them from Linux side. Basically I'm monitoring them from Arduino side. How I switch I2C off from Linux side? Is it possible? About Wire and Wire1, I'm trying to understand which use. Before putting my UDOO on the pcb, I tried it with dupont directly. I'm using THIS library for BMP180 and THIS to read RTC. I tried the BMP085test that doesn't begin Wire or Wire1 in his setup() and I could get data from SDA/SCL from Arduino Side. In setup() the bmp.begin() calls Wire.begin(); I also tried ds3231.ino from the RTC lib and this is its defines: Code: #include <Wire.h> #include "RTClib.h" #ifdef __AVR__ #include <avr/pgmspace.h> #elif defined(ESP8266) #include <pgmspace.h> #elif defined(ARDUINO_ARCH_SAMD) // nothing special needed #elif defined(ARDUINO_SAM_DUE) #define PROGMEM #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) #define Wire Wire1 #endif #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) #if (ARDUINO >= 100) #include <Arduino.h> // capital A so it is error prone on case-sensitive filesystems // Macro to deal with the difference in I2C write functions from old and new Arduino versions. #define _I2C_WRITE write #define _I2C_READ read #else #include <WProgram.h> #define _I2C_WRITE send #define _I2C_READ receive #endif They both worked. In my global sketch I usually use, I put Wire1.begin() before rtc.begin() or bmp.begin(). Should I fix something?
For your case you should modify your external libraries that they always use Wire1 and not Wire See also https://www.udoo.org/docs-neo/Arduino_M4_Processor/Arduino_differences.html
What about the Wire other functions? Should it call Wire1.{beginTransmission/requestFrom/write/send} or Wire.{beginTransmission/requestFrom/write/send}? Is it correct #define Wire Wire1? Shall I call Wire1.begin() in my setup() too? For example, I'm testing only the BMP library. I put: > In the .cpp file, the define. Code: #include "Adafruit_BMP085.h" #define Wire Wire1 > In ino file this is new setup() Code: void setup() { Serial.begin(115200); pinMode(3, OUTPUT); digitalWrite(3, HIGH); //SENSORS on delay(10); if (!bmp.begin()) { Serial.println("Could not find a valid BMP085 sensor, check wiring!"); while (1) {} } } With this configuration, my i2cdetect ends after 1sec and it finds the two sensors (bmp and rtc), BUT I cannot read values from the sketch (begin fails) Code: udooer@udooneo:~$ sudo i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- 77
In details: SSH linux side Code: udooer@udooneo:~$ sudo i2cget -y 1 0x77 0xD0 0x55 In the sketch: Code: Wire1.begin(); uint8_t res = read8(0xD0); [...] uint8_t Adafruit_BMP085::read8(uint8_t a) { uint8_t ret; Wire1.beginTransmission(BMP085_I2CADDR); // start transmission to device #if (ARDUINO >= 100) Wire1.write(a); // sends register address to read from #else Wire1.send(a); // sends register address to read from #endif Wire1.endTransmission(); // end transmission Wire1.beginTransmission(BMP085_I2CADDR); // start transmission to device Wire1.requestFrom(BMP085_I2CADDR, 1);// send data n-bytes read #if (ARDUINO >= 100) ret = Wire1.read(); // receive DATA #else ret = Wire1.receive(); // receive DATA #endif Wire1.endTransmission(); // end transmission return ret; } res is 0xFF
Cool! Just wondering, are you sure you are allowed to put UDOO's logo on a product not manufactured by them?
Hmm Actually it's something I'll ask once I get my code working At the moment is a prototype PCB. I can remove it if it's a problem. But let come back to the topic
I would hardcode change Wire to Wire1 (but I am not a programmer ) I see you use println in your sketches. Be sure you have a serial monitor open to read the serial device (from Arduino IDE or linux minicom). If you do not read your serial data your sketch will stall a couple of seconds after every println! See also https://www.udoo.org/forum/threads/neo-not-reading-serial-dev-ttymcc-slows-down-arduino-m4.4698/
Uhmm the define should do the same effect as change all of them even if fhe documentation is not clear about changing only the begin or everything and when call Wire1. Maybe @Laura or @Francesco knows it. Dont't worry about the println. They will be read by a python script in A9
OK, they changed the documentation! It will soon say: I2C/Wire UDOO Neo M4 Processor has 2 I2C buses wired to the pinout headers and consequentially have 2 Wire objects: Wire: for Brick Connector and SCL/SDA Pins [I2C-2] Wire1: for Motion Sensors (Accelerometer,Magnetometer,Gyroscope) [I2C-4] Be careful and double check when calling Wire.begin() or Wire1.begin() in sketches or libraries. Also check out to have I2C-2 disabled on A9 if you use Wire, and I2C-4 disabled on A9 if you use Wire1.
Wat? It's the opposite from before! Ok so..since I'm using SDA/SCL from internal pins (M4) I set: Wire.begin() in my setup() and I removed it from the library setup. The Udoo devs confirm that Wire.begin() is needed only if there isn't in the library setup. The devs also said to remove i2c-2 from the device tree since I cannot use it from A9. So I removed it. Now I have only UART6 and UART1 set. I dunno if it's correct, but I still see my sensors with i2cdetect -y 1 on A9. Code: [sudo] password for udooer: 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- 77 Software-side should be okay now. Right? Despite of this "fix", the main problem doesn't seems fixed Sometimes the sketch detects the bmp and starts, sometimes it hangs on bmp.begin().
Did you make a support call for this? It would be nice that you or the devs mentioned this as now everybodey can learn.
Of course. I opened a support ticket and I will report any progress. Now they asked for my /boot/uEnv.txt to check if my device tree is correct and working.
You can verify if the kernel is still trying to register i2c-2 by seeing what i2c devices are registered: Code: dmesg | grep i2c
Yes it does. Code: [ 0.107127] i2c i2c-0: IMX I2C adapter registered [ 0.108873] i2c i2c-1: IMX I2C adapter registered [ 0.109634] i2c i2c-2: IMX I2C adapter registered [ 1.376943] i2c /dev entries driver But in my device editor I remove all I2C devices. My uEnv.txt is: Code: udooer@udooneo:~$ cat /boot/uEnv.txt #save this file with unix-like newlines! (\n, 0x0A) video_output=hdmi m4_enabled=true #m4last=/path/to/arduino/sketch.fw #fdt_file=/path/to/custom/devicetree.dtb use_custom_dtb=true Which files should I control?
To find which dtb file is being loaded you need to dump the serial console output of when the board boots (uboot +kernel).
This is my boot output: https://pastebin.com/Ujs9uvZW I used another Udoo to read the boot. I supposed I'm using 'imx6sx-udoo-neo-full-hdmi-m4.dtb'. How to print it? I didn't use the pcb because I had some problems with minicom and dirty characters because I'm at home and I can't solder the pins properly.
You need to de-compile the dtb back to a dts file, to do this you need to checkout the kernel source to get the dtc tool. An example command of how to decompile the dtb : Code: $KERNEL/scripts/dtc/dtc -I dts -O dtb -o <dtb_file> <dts_file>
In /boot/ there're only the .dtb files. Where are .dts? Shall I compile it locally to get .dts? (https://www.udoo.org/docs-neo/Advanced_Topics/Compile_Linux_Kernel.html)