Getting an output for each new measurment from Keithley 2400 - arduino

I am working on a project where I am using a Keithley 2400 Sourcemeter to measure surface conductivity of a specific material. I have a fixed delay number (say 1000 ms) between each measurement (I am using LabTracer 2.0). For the purpose of my project I have to measure the conductivity on three different points on the surface of the specimen. In order to achieve that I am using an Arduino microcontroller which controls the circuit’s endings – three resistors on different places on the surface of the material. The Arduino board starts the process when it is being triggered by the Keithley (when the current flow starts – utilizing analogRead() )
My problem is that the delay time of Keithley is not exactly 1000 ms, and this causes out of sync phenomena.
An ideal solution to this would be if I could get an output in real-time each time a new measurement is taken by the Keithley. In that way I could use this output as a reference to whether open or close the circuit. The analogRead command is useful for the start of the circuit, as it gives an output when the current flow starts. Ideally I would like to receive another output for each new measurement.
The way I am thinking the whole process is this:
Initialization of the circuit by setting resistor_1 to OPEN
Start Keithley
Take measurement
CLOSE resistor_1
OPEN resistor_2
If new measurement is taken then:
CLOSE resistor_2
OPEN resistor_3
If new measurement is taken then:
CLOSE resistor_3
OPEN resistor_1
etc…
Any suggestions on that would be much appreciated. Thanks in advance!

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...

Is it possible to read in data from multiple pins of a microcontroller at the same time?

I am using a PIC24 microcontroller and have multiple inputs. Via these I would like to obtain analog voltage data as fast as possible. I have 8 different data arriving to the microcontroller and I am a bit confused how to solve the problem.
My first idea was to to read in the data sequentially. First from AN0, then AN1 and so forth, but this may take quite a while and I am not at all sure it would be fast enough to do without any other trick. Especially because I do not only want to read in one single value per pin, but an array of voltages, then store and numerically integrate and send the results through USB to the PC. While doing so, new data should be constantly received via the aforementioned pins.
Is it feasible at all what I'm trying to achieve here?
Thanks in advance :)
You should think through your requirements a little more, especially the "at the same time" and "as fast as possible" statements. If you sample each channel within 10 to 100 microseconds of the next would that be satisfactory? What is the maximum frequency of the input signal that you need to detect? Your sampling frequency should be at least double the maximum signal frequency of interest.
Use a single ADC with enough input channels. Configure the ADC so that each time it is triggered to take a sample it will sample all of the channels in sequence (multichannel scan). It won't sample all 8 channels at literally "the same time", but it will cycle through each channel and sample them one after the other at nearly the same time. This could be within a few microseconds depending on the clock rate of the ADC and the channel setup time that you configure.
Now you could configure the ADC to sample in continuous mode where it would start the next sample scan immediately after finishing the previous scan. That would be "as fast as possible" but that might be faster than you need and produce more data than can be processed. Instead you should choose the sampling rate based upon the input signal frequency of interest and setup the ADC to sample at that rate. This rate might be much less than "as fast as possible". You might configure the ADC to collect one sample per channel when it is triggered (single conversion mode) and also setup a hardware timer to expire at the desired sampling rate and trigger the ADC to take a sample scan. The sample period (time between samples) must be greater than the time required to scan all the channels because you won't be able to trigger the ADC again before it has completed the previous channel scan.
If you really need to sample all channels at literally the same time then you probably need a separate ADC for each channel and then trigger all the ADCs to collect a sample at once.

two identical arduino Nano`s running at different speeds?

I am working on a project that requires me to use 2 separate Arduinos running independently from each other. Now, both of these Arduino's are running the same code, but I noticed that after 10 minutes or so, one of them falls behind and this time difference keep increasing with time. Like I already mentioned, the Arduino`s are identical and I bought them at the same time and they are running the same copy of the program. Any ideas what might cause this and how can I fix it?
Thank you.
Here is the link to the Arduino that I bought just in case.
My Arduino modules on Amazon
The Crystal Oszillators have tolerances up to 100ppm (extreme case), which means you could possibly get 16Mhz*100ppm = 1600 clock pulses difference per second. Also the differences of the runtime could be caused by small voltage differences. Even if there is a voltage Regulator on the Board it has small tolerances, based on the fact, that it operates in the Range of MHz this can climb up to an recognizable Offset.
A possible solution is a synchronization of both microcontrollers. I'm not an expert, so the following solution is a possible and easy one, but definitly not the best.
If they are near by each other you can use two pins of each controller. One as Input and one as Output. Write something like this in your code (same for both if you use the same Pins):
digitalWrite(outPin, LOW);
while(digitalRead(inPin)){};
digitalWrite(outPin, HIGH);
Connect the Output from the first to the Input from the second and the same from second to first.
This results in a waiting state for each cycle of the faster Controller until the slower one reaches the same Programm Part. But be careful if one of them stucks somewhere it will stop the second one too. So there is no redundancy! if this was your goal, don't use this method and search for other synchronisation methods.
Perhaps you can use some RTC (real time clock) hardware to help you to keep they synchronised. They are really cheap and easy to use.

Best approach for transfering large data chunks over BLE

I'm new to BLE and hope you will be able to point me towards the right implementation approach.
I'm working on an application in which the peripheral (battery operated) device continuously aggregate sensor readings.
On the mobile side application there will be a "sync" button, upon button press, I would like to transfer all the sensor readings that were accumulated in the peripheral to the mobile application.
The maximal duration between sync's can be several days, hence, the accumulated data can reach a size of 20Kbytes.
Now, I'm wondering what will be the best approach to perform the data transfer from the peripheral to the central application.
I thought about creating an array of characteristics where each characteristic will contain a fixed amount of samples (e.g. representing 1hour of readings).
Then, upon sync, I will:
Read the characteristics count (how many 1hours cells).
Then read the characteristics (1hour cells) one by one.
However, I have no idea if this is a valid approach ?
I'm not sure if this is the most "power efficient" way that I can
use.
I'm not sure if Characteristic READ is the way to go, or maybe
I need to use indication instead.
Any help here will be highly appreciated :)
Thanks in advance, Moti.
I would simply use notifications.
Use one characteristic which you write something to in order to trigger the transfer start.
Then have another characteristic which you simply stream data over by sending 20 bytes at a time. Most SDKs for BLE system-on-a-chips have some way to control the flow of data so you don't send too fast. Normally by having a callback triggered when it is ready to take the next notification.
In order to know the size of the data being sent, you can for example let the first notification contain the size, and rest of them the data.
This is the most time and power efficient way since there can be sent many notifications per connection interval, compared if you do a lot of reads instead which normally requires two round trips each. Don't use indications since they also require basically two round trips per indication. They're also quite useless anyway.
You could possibly increase the speed also by some % by exchanging a larger MTU (which leads to lower L2CAP/ATT headers overhead).

Passing data on to packet for transmission using readstream

I am using the readstream interface to sample at 100hz, I have been able to integrate the interface into Oscilloscope application. I just have a doubt in the way I pass on the buffer value on to the packet to be transmitted . Currently this is how I am doing it :
uint8_t i=0;
event void ReadStream.bufferDone( error_t result,uint16_t* buffer, uint16_t count )
{
if (reading < count )
i++;
local.readings[reading++] = buffer[i];
}
I have defined a buffer size of 50, I am not sure this is the way to do it as I am noticing just one sample per packet even though I have set Nreadings=2.
Also the sampling rate does not seem to be 100 samples/second when I check.I am not doing something right in the way I pass data to the packet to be transmitted.
I think I need to clarify a few things according to your questions and comments.
Reading a single sample from an accelerometer on micaZ motes works as follows:
Turn on the accelerometer.
Wait 17 milliseconds. According to the ADXL202E (the accelerometer) datasheet, startup time is 16.3 ms. This is because this particular hardware is capable of providing first reading not immediately after being powered on, but with some delay. If you decrease this delay, you will likely get a wrong reading, however, the behavior is undefined, so you may sometimes get a correct reading or the result may depend on environment conditions, such as ambient temperature. Changing this 17-ms delay to a lower value is certainly a bad idea.
Read values (in two axes) from the Analog to Digital Converter (ADC), which as an MCU component that converts analog output voltage of the accelerometer to the digital value (an integer). The speed at which ADC can sample is independent from the parameters of the accelerometer: it is another piece of hardware.
Turn off the accelerometer.
This is what happens when you call Read.read() in your code. You see that the maximum frequency at which you can sample is once every 17 ms, that is, 58 samples per second. It may be even a bit smaller because of some overhead from MCU or inaccuracy of timers. This is true when you sample by calling Read.read() in a loop or every fixed interval, because this call itself lasts no less than 17 ms (I mean the delay between the command and the event).
What you may want to do is:
Turn on the accelerometer.
Wait 17 ms.
Perform series of reads.
Turn off the accelerometer.
If you do so, you have one 17-ms delay for a set of samples instead of such delay for each sample. What is important, these steps have nothing to do with the interface you use for performing readings. You may call Read.read() multiple times in your application, however, it cannot be the same implementation of the read command that is already implemented for this accelerometer, because the existing implementation is responsible for turning on and off the accelerometer, and it waits 17 ms before reading each sample. For convenience, you may implement the ReadStream interface instead and call it once in your application.
Moreover, you wrote that ReadStream used a microsecond timer and is independent from the 17-ms settling time of the ADC. That sentence is completely wrong. First of all, you cannot say that an interface uses or does not use a timer. The interface is just a set of commands and events without their definitions. A particular implementation of the interface may use timers. The Read and ReadStream interfaces may be implemented multiple times on different platforms by various hardware components, such as accelerometers, thermometers, hygrometers, magnetometers, and so on. Secondly, the 17-ms settling time refers to the accelerometer, not the ADC. And no matter which interface you use, Read or ReadStream, and which timers a driver uses, milli- or microsecond, the 17-ms delay is always required after powering on the accelerometer. As I mentioned, you probably want to make this delay once per multiple reads instead of once per a single read.
It seems that the TinyOS source code already contains an implementation of the accelerometer driver providing the ReadStream interface which allows you to sample continuously. Look at the AccelXStreamC and AccelYStreamC components (in tos/sensorboards/mts300/).
The ReadStream interface consists of two commands. postBuffer(val_t *buf, uint16_t count) is called to provide a buffer for samples. In the accelerometer driver, val_t is defined as uint16_t. You may post multiple buffers, one by one. This command does not yet start sampling and filling buffers. For that purpose, there is a read(uint32_t usPeriod) command, which directs the device to start filling buffers by sampling with the specified period (in microseconds). When a buffer is full, you get an event bufferDone(error_t result, val_t *buf, uint16_t count) and a component starts filling a next buffer, if any. If there are no buffers left, you get additionally an event readDone(error_t result, uint32_t usActualPeriod), which passes to your application a parameter usActualPeriod, which indicates an actual sampling period and may be different (especially, higher) from a period you requested when calling read due to some hardware constraints.
So the solution is to use the ReadStream interface provided by AccelXStreamC and AccelYStreamC (or maybe some higher-level components that use them) and pass an expected period in microseconds to the read command. If the actual period is lower than one you expect, this means that sampling at higher rate is impossible either due to hardware constraints or because it was not implemented in the ADC driver. In the second case, you may try to fix the driver, although it requires good knowledge of low-level programming. The ADC driver source code for this platform is located in tos/chips/atm128/adc.

Resources