How to program a pressure sensor using the SPI Bus - microcontroller

I am using the STM32 Microcontroller (as part of the LoRa node MB1296D). I want to connect a pressure sensor (MS5803) to the LoRa node and program the sensor via the SPI Bus. Basically, this is all very new to me, which is why I looked up an example code
I am trying to understand this code and a couple of questions have come up:
the macros that are defined in the very beginning, what exactly is their purpose, and are the hexadecimal numbers inherent to the used microcontroller? - If I was to write a code from scratch, I figured I would start by defining macros for the GPIO Pins corresponding to SPI_SCK, SPI_MISO and SPI_MOSI
the function unsigned long cmd_adc(char cmd) contains a switch command, which I have absolutely no clue as on what is does. I mean it looks to me as if I am trying to set the resolution of the ADC, but how do I know the corresponding delay and why does the switch command contain the 0x0f ?
So. If you could find some time to give me a useful answer, that'd be great! Also, if you know any good readings with special focus on this topic, please tell me! I am trying to tackle this problem with little time available.

Your questions are basic C programming questions and are not really specific to this pressure sensor or example.
The macros are defined with hexadecimal numbers to make it clear that the values represent bit fields. It's very easy (and second nature for embedded software developers) to convert hexadecimal to binary. Read the register descriptions in the sensor's datasheet. The bits set in the hexadecimal values will correspond to meaningful bits in the sensor's register description.
switch (cmd & 0x0f) performs a bitwise AND of the cmd with 0x0f. The hexadecimal value 0x0f has the four least significant bits set. So the code is ignoring (i.e., masking off or zeroing out) the four most significant bits of cmd and considering only the four least significant bits of the cmd value.

Related

Can't get temperature reading out of ble beacon .. at my wits end now. This needs a super-hero I guess

I have a task where I need to read 2 parameters from a BLE Beacon. The documentation was seriously lacking and after a fair amount of effort, I managed to get some basic information about reading the data from the BLE Beacon.
The parameters to read are
1) Battery Voltage of the sensor
2) Temperature the beacon has a built in temperature sensor.
I think I have tried almost every popular Python BLE library out there but I just can't seem to get the temperature reading out of the beacon. "I think" I am able to read the voltage. The reason why I said "I think" is because the value seems to match what was provided in the minimal document. And also when I put the beacon into the charger, I can see the value go up - an indication that it is the voltage reading. As I could not read the temperature ( because the UUIDs that are mentioned in the document, the value doesn't seem to change ). I have tried enabling the sensor in every possible way and method described - by writing 01:00 etc. I spent a fair amount of time to reverse engineer the thing. I ran a packet sniffer and managed to capture the data that was being transferred between the beacon and the mobile app ( They have a mobile app ). But then again I am not able to figure out how the temperature readings are being communicated between the beacon and the app. Let me break the whole stuff in smaller blocks.
Hardware: BLE beacon from which voltage and temperature can be read. The temperature sensor is built into the beacon. And the beacon itself is from Texas Instruments but the temperature, voltage sensing part is done by a third party. They provided us with some minimal information and it was difficult to make sense of some of the sentences as they have trouble communicating in English.
The sequence to get the data goes like this
Scan for beacons
When the beacon is found then connect to it
Enable notification
Set notification interval
Get the voltage and temperature reading.
I have been able to do the first 4 real fast, and "half" of No. 5, i.e getting the voltage part. When I say real fast I mean I got that stuff with nearly no documentation available at that time.
As per the info that I have the data resides in these characteristics/UUIDs. Also please note that the UUID are not standard 128 bit and this caused me issues when using certain libraries. But after some tries I got to read/write to them using handles etc. The handles and other stuff I printed are ones that I read using PYGATT (A Python wrapper for gatttool).
The UUIDs are marked as 1st, 2nd, 3rd and 4th parameters and it has the following to say about the parameters
- A: 1 byte (2nd Param)
- B: Maj + Min values, 4 bytes (4th Param)
- C: 4 bytes (3rd Param)
- D: Enable/disable notification ( I have been able to turn this on )
- E: Set notification interval ( I have been able to set this and can notice the change in notification interval )
This is minimal so as to not have a large file. All it does is this - the mobile app connects to the beacon, then the notifications start and the temperate readings are retrieved by the mobile app. Like I had mentioned, I don't seem to have problem reading the voltage, it's only the temperature that I am getting stuck at. I have been at it for a week now. I think I have tried nearly everything that I could think of. I even enumerated all the writable characteristics and tried writing numbers like 1 ( enables the sensor? ). I could have offered a bounty for this straight away if it were possible. I rarely get stuck for so long with a problem. This is driving me a little crazy. I am getting close to my wits end - I guess it's time for a super hero - anyone out there? :) I can provide for every bit of information needed if someone could indicate what is wrong. I even wrote a cordova app ... and tried a bunch of stuff from my Android phone. I can connect ... write to characteristics, read stuff etc but temperature ready, nah!!! It just won't budge. All I get is the same set of values ( I used a JSON.stringify to display A, B and C). I can bother about the byte order later. I guess that is a smaller problem.
The communication between the beacon and a third party mobile app is fine, it is able to read the temperature info just fine.
I have been looking at wireshark data and I am fairly sure that the temperature data is being communicated at this stage. But then when I decode the "value", it looks like it's the voltage. It mentions l2cap but I am not sure how that is being used here to send the temperature readings ( if it is using that in the first place ).
Update: Wrote to every writable characteristics. Wrote values like 1, 0100, 2, 7 on every writable characteristics. At the same time I was reading every readable characteristic ( in a loop ) and doing a comparison (just true/false) with the previous set of values. This seemed like a quick and easier way to know if something changed. Didn't want to take chances with converting the hex to a float. I can figure out the byte order later.
From the sniffed data (wireshark) I can only see 3 writes happening on the beacon.
I am not fully sure, even after a long discussion, but it seems that the four bytes of the notification are used for the voltage as well as the temperature, since the temperature can most probably be derived from the voltage.
From the values it seems that those four bytes represent the voltage in float (if you ignore the absurd factor of 10^-38 that comes in because only 4 bytes instead of 8 bytes are used).
Since typically the temperature T is derived from a resistivity measurement, where the resistivity R is proportional to the voltage U (if the current is constant), you can in principle calculate the temperature T from the voltage U.
The problem is that T(R) is relatively linear, but not perfectly (in contrast to U(R) which is assumed to be U=RI). So you may need to plot the values for T(U) to find out the curve that they are using.
To add to the confusion, I got the best results when only using the first five bits of the third byte and the eight bits of the fourth byte. I am not aware why this is the case, and it might point to some trouble still.
The best option is to ask for their function T(U) that they are using. If they can and will provide it for you...

PIC24F - Set LATx specific pins without effecting the other pins

Is there a way to set specific port pins without effecting other pins at the same port?
For example:
I used LATB[13:6] for 7-segment LCD, the rest LATB bits are used for other purposes.
Now I need to set LATB = 0x003F for display '0', if i do this the rest of the bits are changed.
Someone can help me?
You'll have to split the operation, since you can't address specifically bits 6 to 13 in a 16 bit register. For instance, assuming LATB is a 16 bit register on which bits 6 to 13 (a range of 8 bits) map to a 7-segment display with period (making 8 segments), and we want to set those pins in particular to 0x3f = 0b00111111, we can do:
LATB = (LATB & ~(0xff<<6)) | (0x3f<<6);
0xff is a bit mask of which bits we want to affect, representing 8 bits, which we shift into position 6-13 using <<6.
However, this is not atomic; we are reading, masking out the bits we want to adjust, setting them to new values, and writing back the entire register including the preserved other bits. Thus we may need for instance to disable interrupts around such a line.
For many MCUs there are particular code paths supporting modification of single bits, or dedicated logic for clear/set. Those might mean that you could perform the adjustment without risking trampling another change if you stick to plainer operations, such as:
val = 0x3f;
LATB |= (val<<6); // set bits which should be set
LATB &= (val<<6) | ~(0xff<<6); // clear bits that should be clear
In this example, we're not doing the display update in one step, but each update we are making is left in a form the compiler might be able to optimize to a single instruction (IOR and AND, respectively).
Some processors also have instructions to access sections of a word like this, frequently named bitfield operations. I don't think PIC24 is among those. It does have single-bit access instructions, but they seem to either operate on the working file or require fixed bit positions, which means setting bit by bit would have to be unrolled.
C also does have a concept of bit fields, which means is is possible to define a struct interpretation of the latch register that does have a name for the bits you want to affect, but it's a fairly fragile method. You're writing architecture specific code anyway when relying on the particular register names. It is likely best to inspect documentation for your compiler and platform libraries.

How to write for reserved bits during SPI communication in Arduino Due?

I am interfacing an Arduino device to a Phase Locked Loop chip using SPI, however have become confused about how to write the data I need to input. Note the following latch summaries
Latch Summaries
Note how in the reference counter latch, the most significant bit (DB23) is noted as x. The same can be said of DB23 and DB22 in the N Counter Latch.
What does this 'x' mean? Also, if I want to transfer data, how would I do this? What would I put in place of the x?

LCD Wrong Characters

i'm very young in the world of Arduino and i'm having a serious problem with the LCD QC2004A and Arduino Mega because whatever i write in alphanumeric, is translated to chinese language and i really don't know what to do to change it.
I have already searched in too many websites and i saw nobody who has already discovered the solution for this thing.
As you can see on the figure bellow, the diference between the chinese alphabet and alphanumeric is only the first number of the upper 4 bits which is responsable for the alphabets is always "1" and i don't know how to put it in "0".
Table 4 Correspondence between Character Codes and Character Patterns (ROM Code: 0A)
I believe that DB4 is responsable for this number, but i don't know.
Is there any way to change the state of a DBx in the LCD, maybe try to define this DBx to be always 0 ?
I tryed to connect on the ground but it did not workd
Telling from this QC2004A datasheet your display uses a KS0066-compatible display controller which in turn should work with any HD44780 LCD software library.
If all 8 data lines (usually pins 7-14) on your LCD are connected, make sure your display library is configured for 8-Bit mode.
If only 4 lines (pins 11-14) are connected, then double check that your software is configured for 4-Bit mode.
If you are able to read what you expected the LCD to display by changing Bit 7 (not Bit 4) on each character (using your character table and a piece of paper), your software library might need to be configured to use the latin instead of the kana character set.
If that manual translation does not yield anything comprehensible, double check your wiring especially on LCD pins 7-14 (or 11-14 for 4-Bit mode). The IO pins on your arduino might be placed out of order.
If the text on your display is mixed latin-kana, you might be using the wrong ROM Code A00 instead of A02 (see HD44780 datasheet table 4).
If all that fails, try another LCD software library to rule out software issues.

How to read multiple Analog sensor

I am using Arduino UNO board. I have 24 analog channel which gives me 0~5v analog out put. Now my problem is I have only 5 analog channel. I wanted to read value from each channel for every 2 min and then switch to other channel. Can anyone suggest me in Hardware how can get analog value ?
I am planning to use 8:1 multiplexer or 16:1 multiplexer . Will it is correct way of doing it. Can you suggest other way of doing it in hardware ?
74HC4051,74HCT4051,ADG708,MD14051B,
IC I am planning to Use.dep[end on so,s1,s2 just switch the channel
As a start, you might need to know that even Arduino Uno also have internal MUX. In my experience of reading multiple analog channel, this is the approach that I take. However by taking this approach, I suggest you to recheck the analog value so adding MUX will not generate any error or bias.
This could be done by comparing the output of measurement with the MUX and output of measurement without the MUX. I used 74HC4051 and it works brilliantly, just make sure not to leave any pin floating. The only disadvantage of this method is that you will need to use some I/O to control the MUX, but if that is not an issue for you, then go ahead.
Any other method could be more complicated. It would require your analog channels to correlate with each other, and you need to find a way method to combine multiple analog channel into a single channel.
e.g: if your aim is to compare two analog value, instead of measuring the value and comparing the value in software, you could make use of op-amp comparison circuit to compare the value for you and take the comparison result instead.
Use the photon-pixel coupling method, it is a new approach in science for sampling an unlimited number of sensors in parallel.
Basically, each sensor output is an LED. If you have 10000 sensors, the output of all of them is inserted in a LED array, a LED matrix as the authors say. After that, the LED array is filmed by a video camera and the images are processed in real time by a computer. A software reads one pixel from each LED from the LED array and converts it to numerical values. So, your LED array will be converted in a matrix (with 10000 elements) filled with numbers that can be processed as you wish in your software. I don't know if I was explicit but you can read their article here: https://www.sciencedirect.com/science/article/pii/S2215016119300901
Note that classic multiplexing is serial, this approach is parallel.
The photon-pixel coupling method is truly ingenious because it solves two main problems in engineering: an unlimited number of sensors and their parallel sampling at video rate frequencies. Just imagine, we can read as many sensors as we wish. What I wander is if we can adapt the photon-pixel coupling to Arduino. I am new in the world of microcontrollers but I know Arduino can support a cam, so it should be possible.
If you are a PhD student then:
P.A. Gagniuc, C. Ionescu-Tirgoviste, R.G. Serban, E. Gagniuc. Photon-pixel coupling: A method for parallel acquisition of electrical signals in scientific investigations. MethodsX, 6:968-979, 2019.
To read more analog channels than inputs you have, an analog multiplexer is a good option. All the ones you suggested will work, but personally, I like the Analog Devices ICs for analog circuits, so I would take the ADG708, but this is just a personal preference.

Resources