Getting notified when an I2C-Value changes in C++ - c++

I recently started experimenting with I2C-Hardware on my raspberry pi. Following this tutorial Using the I2C interface I already know how to read and set values. However, the program I want to realize needs the current value on a specific address all the time. So, I made a thread and query the value constantly in a never ending loop, which seems primitive to me. Is it possible to get notified in an event-like manner when a value on an I2C-adress changes?
A platform independend solution would also be much welcomed.

I was able to get what I wanted.
I use the following repeater for the I2C-Bus: link and it turns out there is a soldering bridge (LB2) you can set that sets a signal on GPIO17 whenever a value on the I2C-Bus changes since it has last been changed. I can now listen on this events accordingly.

Generally speaking, the I2C bus has no interrupt capability. So with only I2C, all you can do is poll the chip for a certain event to happen or value to change.
Most chips do have an interrupt line (sometimes even more than one) that can be programmed to trigger on certain events. The behavior of this line depends on the chip. Usually it needs to be enabled (using I2C commands) and it needs to be linked to a GPIO input line. For these, interrupt support is available.

Related

NTPD synchronization with 1PPS signal

I have an AHRS (attitude heading reference system) that interfaces with my C++ application. I receive a 50Hz stream of messages via Ethernet from the AHRS, and as part of this message, I get UTC time. My system will also have NTPD running as the time server for our embedded network. The AHRS also has a 1PPS output that indicates the second roll-over time for UTC. I would like to synchronize the NTPD time with the UTC. After some research, I have found that there are techniques that utilize a serial port as input for the 1PPS. From what I can find, these techniques use GPSD to read the 1PPS and communicate with NTPD to synchronize the system time. However, GPSD is expecting a NMEA formatted message from a GPS. I don't have that.
The way I see it now, I have a couple of optional approaches:
Don't use GPSD. Write a program that reads the 1PPS and the Ethernet
message contain UTC, and then somehow communicates this information
to NTPD.
Use GPSD. Write a program that repackages the Ethernet message into
something that can be sent to GPSD, and let it handle the
interaction with NTPD.
Something else?
Any suggestions would be very much appreciated.
EDIT:
I apologize for this poorly constructed question.
My solution to this problem is as follows:
1 - interface 1PPS to RS232 port, which as it turns out is a standard approach that is handled by GPSD.
2 - write a custom C++ application to read the Ethernet messages containing UTC, and from that build an NMEA message containing the UTC.
3 - feed the NMEA message to GPSD, which in turn interfaces with NTPD to synchronize the GPS/1PPS information with system time.
I dont know why you would want drive a PPS device with a signal that is delivered via ethernet frames. Moreover PPS does not work the way you seem to think it does. There is no timecode in a PPS signal so you cant sync the time to the PPS signal. The PPS signal is simply used to inform the computer of how long a second is.
there are examples that show how a PPS signal can be read in using a serial port, e.g. by attaching it to an interrupt capable pin - that might be RingIndicator (RI) or something else with comparable features. the problem i am seeing there is that any sort of code-driven service of an interrupt has its latencys and jitter. this is defined by your system design (and if you are doing it, by your own system tailored special interrupt handler routine - on a PC even good old ISA bus introduced NMI handlers might see such effects).
to my best understanding people that are doing time sync on a "computer" are using a true hardware timer-counter (with e.g. 64 bits) and a latch that gets triggered to sample and hold the value of the timer on every incoming 1PPS pulse. - folks are doing that already with PTP over the ethernet with the small variation that a special edge of the incoming data is used as the trigger and by this sender and receiver can be synchronized using further program logic that grabs the resulting value from the built in PTP-hardware-latch.
see here: https://en.wikipedia.org/wiki/Precision_Time_Protocol
along with e.g. 802.1AS: http://www.ieee802.org/1/pages/802.1as.html
described wikipedia in section "Related initiatives" as:
"IEEE 802.1AS-2011 is part of the IEEE Audio Video Bridging (AVB) group of standards, further extended by the IEEE 802.1 Time-Sensitive Networking (TSN) Task Group. It specifies a profile for use of IEEE 1588-2008 for time synchronization over a virtual bridged local area network (as defined by IEEE 802.1Q). In particular, 802.1AS defines how IEEE 802.3 (Ethernet), IEEE 802.11 (Wi-Fi), and MoCA can all be parts of the same PTP timing domain."
some article (in German): https://www.elektronikpraxis.vogel.de/ethernet-fuer-multimediadienste-im-automobil-a-157124/index4.html
and some presentation: http://www.ieee802.org/1/files/public/docs2008/as-kbstanton-8021AS-overview-for-dot11aa-1108.pdf
my rationale to your question is:
yes its possible. but it is a precision limited design due to the various internal things like latency and jitter of the interrupt handler you are forced to use. the achievable overall precision per pulse and in a long term run is hard to say but might be in the range of some 10 ms at startup with a single pulse to maybe/guessed 0,1 ms. - doing it means proving it. long term observations should help you unveiling the true practical caps with your very specific computer and selected software environment.

Raspberry pi lockup when reading data from MPU6050+BMP180

I am trying to write a flight control program for quadcopter, and all my code can be found on https://github.com/sgsdxzy/adc
My 10DOF sensor board is GY87, which consists of 3 I2C devices: MPU6050, HMC5883L and BMP180(same API as BMP085). I use i2cdevlib and pigpio to get data from sensors.
MPU6050 can use I2C slaves, and I set HMC5883L as its slave. I successfully got DMP running. MPU6050 can generate an interrupt when DMP data is ready and send the data to a fifo. I wired the interrupt to a gpio, and used pigpio's gpioSetAlertFunc() to monitor it's status. If an interrupt is generated, my program will read the fifo and get DMP data, then write them to some (thread-safe) global variables. This alone is working well.
BMP180 is a relatively simpler device, which you set some register to change mode and wait for some time, then read other registers to get results. This alone is working well too.
However, when I combined the two, a random system lockup occured: I set the interrupt handler, then enter a loop: every 0.1s I set BMP180 to measure and get it's data, then print all global variables on screen; MPU6050 just generate 100 interrupts per second and my program handled them in time, so every 0.1s I get the latest data. This works quite well with correct results for several loops, but then at a random point the program stucks, and top shows it's using up 2 cores.
Remove either
1) the interrupt handling
2) or the measure of BMP180 in every loop
and the program will just run flawlessly and I tested it can ran stable for at least half an hour.
But combining two it will always stuck using up all processor power, either after 10 seconds or 1 minute.
I just can't understand why, could someone point out what's wrong? Or at least teach me how to debug what causes the lockup (using which tool, as the lockup happens at a random point and there are too many procedures, using gdb to run the program step-by-step isn't an option)
Thanks in advance.
All right, I found out the i2cdevlib is not thread-safe, and caused the problem.
As i2cdevlib's api is so far from pigpio, porting all these codes to pure pigpio is not trival. Currently I will get do with a pthread mutex to let only one thread access i2c at the same time.

Modify time until DBT_DEVICEREMOVECOMPLETE is sent

Is there a way to trigger the USB Device Discovery of Windows, such that removed devices are detected faster?
I have a USB Serial modem that I unplug (the USB plug, not the serial one). I want to detect the DBT_DEVICEREMOVECOMPLETE event which is sent as soon as the unplugging is detected (That's what I assume). The detection of the Event works as desired, it is sent sometimes 1s after removal, sometimes several minutes after removal.
Is there a way to decrease the refresh interval, or another way to make this event getting sent faster?
Well, the problem here is that DBT_DEVICEREMOVECOMPLETE is sent after Windows decides it has detected the removal, and you can't influence that, at least not in the general case. There are various things that make Windows do this faster or slower (type of device, current "data flow" with the device, the device itself), and it also varies between OS versions. What I found helps to some degree in some of cases is to remove, from the Registry, references to USB devices that were plugged into that USB port before (there are various utilities for this).
At the extreme, since this is a Windows Broadcast message (non-queued), there will not be another one sent in until the previous is processed. Thus, you may not receive it at all! To solve that, keep message handling fast and simple and don't set a breakpoint there while debugging.
Also, having a separate Windows and Thread for the specific purpose of handling USB device arrival/removal notifications may help.
But, from my experience, polling will not help, as the main problems seems to be in the criteria Windows uses to detect the removal. The time from that event until you receive the message is small. Of course, in your case this may not be true - to find out, use a tool like SysInternals Process Monitor. Depending on what you see going on there, there may be something you can do to make it faster.

Handle GPIO Button event with C++

Hi guys I need some help. I am making a c++ embedded application in an ARM. I need to get a push button event, I was looking for in internet and I find that the best way to do it is with interruptions. I know that I can set one pin through terminal like this "echo raise > /sys/.../gpio/gpio81/edge". But I need to know how can I get the interrupt from my C++ application when it happend, I just need some example, because I do not know if I have to use some special library.
Thank you guys I hope someone can help me.
Manual 'mechanical' pushbuttons require debouncing. That, and the fact that pushing buttons does not require high I/O performance, means that a GPIO interrupt is an awkward overkill. It can' of course, be done, but it's easier and safer to poll the GPIO port with a timer interrupt, storing the state of the inputs and comparing with the previous state/s. If a GPIO line has changed state for a sufficient number of samples, you have your button event and can act on it.
If you are using a tasking OS, you could hook the existing timer interrupt - it's only a few instructions to handle the GPIO poll so you should not see any noticeable performace hit. If is is decided that the button/s have been pressed/released, you can signal a semaphore so that a waiting thread can quickly process the event.
Hi guys I find the solution what I just wanted is here:
https://developer.ridgerun.com/wiki/index.php/Gpio-int-test.c
Thank you anyways

How to check if an application is in waiting

I have two applications running on my machine. One is supposed to hand in the work and other is supposed to do the work. How can I make sure that the first application/process is in wait state. I can verify via the resources its consuming, but that does not guarantee so. What tools should I use?
Your 2 applications shoud communicate. There are a lot of ways to do that:
Send messages through sockets. This way the 2 processes can run on different machines if you use normal network sockets instead of local ones.
If you are using C you can use semaphores with semget/semop/semctl. There should be interfaces for that in other languages.
Named pipes block until there is both a read and a write operation in progress. You can use that for synchronisation.
Signals are also good for this. In C it is called sendmsg/recvmsg.
DBUS can also be used and has bindings for variuos languages.
Update: If you can't modify the processing application then it is harder. You have to rely on some signs that indicate the progress. (I am assuming you processing application reads a file, does some processing then writes the result to an output file.) Do you know the final size the result should be? If so you need to check the size repeatedly (or whenever it changes).
If you don't know the size but you know how the processing works you may be able to use that. For example the processing is done when the output file is closed. You can use strace to see all the system calls including the close. You can replace the close() function with the LD_PRELOAD environment variable (on windows you have to replace dlls). This way you can sort of modify the processing program without actually recompiling or even having access to its source.
you can use named pipes - the first app will read from it but it will be blank and hence it will keep waiting (blocked). The second app will write into it when it wants the first one to continue.
Nothing can guarantee that your application is in waiting state. You have to pass it some work and get back a response. It might be transactions or not - application can confirm that it got the message to process before it starts to process it or after it was processed (successfully or not). If it does not wait, passing a piece of work should fail. Whether when trying to write to a TCP/IP socket or other means, or if timeout occurs. This depends on implementation, what kind of transport you are using and other requirements.
There is actually a way of figuring out if the process (thread) is in blocking state and waiting for data on a socket (or other source), but that means that client should be on the same computer and have access privileges required to do that, but that makes no sense other than debugging, which you can do using any debugger anyway.
Overall, the idea of making sure that application is waiting for data before trying to pass it that data smells bad. Not to mention the racing condition - what if you checked and it was OK, and when you actually tried to send the data, you found out that application is not waiting at that time (even if that is microseconds).