Class similar to AnalogIn that uses burst mode to run continious background conversions so when the input is read, the last value can immediatly be returned.

Dependents:   KL25Z_FFT_Demo test_armmath KL25Z_FFT_Demo_tony KL25Z_FFT_Demo_tony ... more

Supported devices

  • LPC1768
  • LPC4088
  • LPC11u24
  • KLxx
  • K20D50M

Introduction

When you read an AnalogIn object it will enable the corresponding ADC channel, depending on the implementation do either one or multiple measurements for more accuracy, and return that value to your program. This way the ADC is only active when it is required, and it is fairly straightforward. However the downside is, is that an ADC is relatively slow. On the LPC1768 it runs at 200kHz -> in that time it could also have done 500 instructions.

FastAnalogIn

This library uses the 'burst' feature of the microcontroller. This allows the ADC on the background to perform the AD conversions without requiring intervention from the microcontroller's core. Also there are no interrupts used, so also your time-sensitive code is not affected.

What the burst feature does is check which AD-channels are enabled, and he converts the enabled AD-channels one at a time. The result he stores in a register, where each channel has its own register. So this library checks which pins are used (you may make several FastAnalogIn objects, both for different pins and for the same pin, generally not extremely useful, but it is supported), and enables the relevant channels.

Reading a pin is done exactly the same for the user as AnalogIn, the read and read_us functions both work the same, and also the float operator is supported. However now it doesn't have to start a new conversion, so minus some overhead it can almost directly return the last measured value, no need to wait on the ADC!

Enable/Disable

FastAnalogIn has a few extra options that normal AnalogIn does not have: specifically you can either choose to have a FastAnalogIn object enabled or disabled. This is done with either the enable(bool enabled) and disable() functions, where enable(false) is equal to disable(), or by adding a second true/false argument to the constructor to either have it enabled at the beginning or disabled. By default it will be enabled.

LPC1768 & LPC4088
When a FastAnalogIn object is enabled, its corresponding ADC channel is also being scanned by the ADC and so it works as described above. When it is disabled you can still use the read functions, only now it will only enable the ADC channel for one conversion (actually two since for some reason the first conversion seems a bit weird), and when that conversion is done it will disable it again.

Since the ADC has to do the conversions one channel at a time, it becomes slower per channel if you enable many channels. For example, if you want to sample a sensor at a very high rate, and you also want to monitor your battery voltage. Then there is no reason to run an AD conversion on your battery continiously, so you can disable that channel and only run it once in a while.

KLxx
Multiple Fast instances can be declared of which only ONE can be continuous (all others must be non-continuous).
Example:

FastAnalogIn   speed(PTC2);           // Fast continuous
FastAnalogIn   temp1(PTC2, 0);        // Fast non-continuous.
FastAnalogIn   temp2(PTB3, 0);        // Fast non-continuous.

Downsides

Of course there are always downsides present. The extra power consumption probably won't be relevant for most, but still it is there. Aditionally there is no median filter like the normal AnalogIn has. Finally if you use AnalogIn you know exactly when the conversion happened, with FastAnalogIn you only know it was recently done but not exactly when.

AnalogIn + FastAnalogIn

Don't run both AnalogIn and FastAnalogIn objects in parallel as the results are unpredictable.
Both objects modify microcontroller registers, and neither of them bothers to inform the other one.
That's also the reason the disable() function was added.

Committer:
frankvnk
Date:
Sat Mar 08 15:44:57 2014 +0000
Revision:
2:9b61d0792927
Parent:
0:c2a7b899e6c7
Child:
3:a9b753c25073
Added KLxx support

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sissors 0:c2a7b899e6c7 1 #ifndef FASTANALOGIN_H
Sissors 0:c2a7b899e6c7 2 #define FASTANALOGIN_H
Sissors 0:c2a7b899e6c7 3
Sissors 0:c2a7b899e6c7 4 /*
Sissors 0:c2a7b899e6c7 5 * Includes
Sissors 0:c2a7b899e6c7 6 */
Sissors 0:c2a7b899e6c7 7 #include "mbed.h"
Sissors 0:c2a7b899e6c7 8 #include "pinmap.h"
Sissors 0:c2a7b899e6c7 9
frankvnk 2:9b61d0792927 10 #if !defined TARGET_LPC1768 && !defined TARGET_KL25Z && !defined TARGET_KL46Z && !defined TARGET_KL05Z
Sissors 0:c2a7b899e6c7 11 #error "Target not supported"
Sissors 0:c2a7b899e6c7 12 #endif
Sissors 0:c2a7b899e6c7 13
frankvnk 2:9b61d0792927 14 /** A class similar to AnalogIn, only faster, for LPC1768 and KLxx
frankvnk 2:9b61d0792927 15 *
frankvnk 2:9b61d0792927 16 * AnalogIn does a single conversion when you read a value (actually several conversions and it takes the median of that).
frankvnk 2:9b61d0792927 17 * This library runns the ADC conversion automatically in the background.
frankvnk 2:9b61d0792927 18 * When read is called, it immediatly returns the last sampled value.
frankvnk 2:9b61d0792927 19 * Using more ADC pins in continuous mode will decrease the conversion rate.
frankvnk 2:9b61d0792927 20 * If you need to sample one pin very fast and sometimes also need to do AD conversions on another pin,
frankvnk 2:9b61d0792927 21 * you can disable the continuous conversion on that ADC channel and still read its value.
frankvnk 2:9b61d0792927 22 * When continuous conversion is disabled, a read will block until the conversion is complete (much like the regular AnalogIn library does).
frankvnk 2:9b61d0792927 23 * Each ADC channel can be enabled/disabled separately.
frankvnk 2:9b61d0792927 24 *
frankvnk 2:9b61d0792927 25 * IMPORTANT NOTES
frankvnk 2:9b61d0792927 26 * ---------------
frankvnk 2:9b61d0792927 27 * - When used with KLxx processors, this library can coexist with the regular AnalogIn library.
frankvnk 2:9b61d0792927 28 * - When used with the LPC1768 processor, it does not play nicely with regular AnalogIn objects,
frankvnk 2:9b61d0792927 29 * so either use this library or AnalogIn, not both at the same time!!
frankvnk 2:9b61d0792927 30 *
frankvnk 2:9b61d0792927 31 * Example for the KLxx processors:
frankvnk 2:9b61d0792927 32 * @code
frankvnk 2:9b61d0792927 33 * // Print messages when the AnalogIn is greater than 50%
frankvnk 2:9b61d0792927 34 *
frankvnk 2:9b61d0792927 35 * #include "mbed.h"
frankvnk 2:9b61d0792927 36 *
frankvnk 2:9b61d0792927 37 * FastAnalogIn temperature(PTC2); //Fast sampling on PTC2
frankvnk 2:9b61d0792927 38 * AnalogIn speed(PTB3); //Normal sampling on PTB3
frankvnk 2:9b61d0792927 39 *
frankvnk 2:9b61d0792927 40 * int main() {
frankvnk 2:9b61d0792927 41 * while(1) {
frankvnk 2:9b61d0792927 42 * if(temperature > 0.5) {
frankvnk 2:9b61d0792927 43 * printf("Too hot! (%f) at speed %f", temperature.read(), speed.read());
frankvnk 2:9b61d0792927 44 * }
frankvnk 2:9b61d0792927 45 * }
frankvnk 2:9b61d0792927 46 * }
frankvnk 2:9b61d0792927 47 * @endcode
frankvnk 2:9b61d0792927 48 * Example for the LPC1768 processor:
frankvnk 2:9b61d0792927 49 * @code
frankvnk 2:9b61d0792927 50 * // Print messages when the AnalogIn is greater than 50%
frankvnk 2:9b61d0792927 51 *
frankvnk 2:9b61d0792927 52 * #include "mbed.h"
frankvnk 2:9b61d0792927 53 *
frankvnk 2:9b61d0792927 54 * AnalogIn temperature(p20);
frankvnk 2:9b61d0792927 55 *
frankvnk 2:9b61d0792927 56 * int main() {
frankvnk 2:9b61d0792927 57 * while(1) {
frankvnk 2:9b61d0792927 58 * if(temperature > 0.5) {
frankvnk 2:9b61d0792927 59 * printf("Too hot! (%f)", temperature.read());
frankvnk 2:9b61d0792927 60 * }
frankvnk 2:9b61d0792927 61 * }
frankvnk 2:9b61d0792927 62 * }
frankvnk 2:9b61d0792927 63 * @endcode
Sissors 0:c2a7b899e6c7 64 */
Sissors 0:c2a7b899e6c7 65 class FastAnalogIn {
Sissors 0:c2a7b899e6c7 66
Sissors 0:c2a7b899e6c7 67 public:
Sissors 0:c2a7b899e6c7 68 /** Create a FastAnalogIn, connected to the specified pin
Sissors 0:c2a7b899e6c7 69 *
Sissors 0:c2a7b899e6c7 70 * @param pin AnalogIn pin to connect to
Sissors 0:c2a7b899e6c7 71 * @param enabled Enable the ADC channel (default = true)
Sissors 0:c2a7b899e6c7 72 */
Sissors 0:c2a7b899e6c7 73 FastAnalogIn( PinName pin, bool enabled = true );
Sissors 0:c2a7b899e6c7 74
frankvnk 2:9b61d0792927 75 ~FastAnalogIn( void )
frankvnk 2:9b61d0792927 76 {
frankvnk 2:9b61d0792927 77 disable();
frankvnk 2:9b61d0792927 78 }
Sissors 0:c2a7b899e6c7 79
Sissors 0:c2a7b899e6c7 80 /** Enable the ADC channel
Sissors 0:c2a7b899e6c7 81 *
Sissors 0:c2a7b899e6c7 82 * @param enabled Bool that is true for enable, false is equivalent to calling disable
Sissors 0:c2a7b899e6c7 83 */
Sissors 0:c2a7b899e6c7 84 void enable(bool enabled = true);
Sissors 0:c2a7b899e6c7 85
Sissors 0:c2a7b899e6c7 86 /** Disable the ADC channel
Sissors 0:c2a7b899e6c7 87 *
Sissors 0:c2a7b899e6c7 88 * Disabling unused channels speeds up conversion in used channels.
Sissors 0:c2a7b899e6c7 89 * When disabled you can still call read, that will do a single conversion (actually two since the first one always returns 0 for unknown reason).
Sissors 0:c2a7b899e6c7 90 * Then the function blocks until the value is read. This is handy when you sometimes needs a single conversion besides the automatic conversion
Sissors 0:c2a7b899e6c7 91 */
Sissors 0:c2a7b899e6c7 92 void disable( void );
Sissors 0:c2a7b899e6c7 93
Sissors 0:c2a7b899e6c7 94 /** Returns the raw value
Sissors 0:c2a7b899e6c7 95 *
Sissors 0:c2a7b899e6c7 96 * @param return Unsigned integer with converted value
Sissors 0:c2a7b899e6c7 97 */
Sissors 0:c2a7b899e6c7 98 unsigned short read_u16( void );
Sissors 0:c2a7b899e6c7 99
Sissors 0:c2a7b899e6c7 100 /** Returns the scaled value
Sissors 0:c2a7b899e6c7 101 *
Sissors 0:c2a7b899e6c7 102 * @param return Float with scaled converted value to 0.0-1.0
Sissors 0:c2a7b899e6c7 103 */
frankvnk 2:9b61d0792927 104 float read( void )
frankvnk 2:9b61d0792927 105 {
frankvnk 2:9b61d0792927 106 unsigned short value = read_u16();
frankvnk 2:9b61d0792927 107 return (float)value/65535;
frankvnk 2:9b61d0792927 108 }
Sissors 0:c2a7b899e6c7 109
Sissors 0:c2a7b899e6c7 110 /** An operator shorthand for read()
Sissors 0:c2a7b899e6c7 111 */
Sissors 0:c2a7b899e6c7 112 operator float() {
Sissors 0:c2a7b899e6c7 113 return read();
Sissors 0:c2a7b899e6c7 114 }
Sissors 0:c2a7b899e6c7 115
Sissors 0:c2a7b899e6c7 116
Sissors 0:c2a7b899e6c7 117 private:
Sissors 0:c2a7b899e6c7 118 static int channel_usage[8];
Sissors 0:c2a7b899e6c7 119 bool running;
Sissors 0:c2a7b899e6c7 120 char ADCnumber;
Sissors 0:c2a7b899e6c7 121 uint32_t *datareg;
Sissors 0:c2a7b899e6c7 122 };
Sissors 0:c2a7b899e6c7 123
frankvnk 2:9b61d0792927 124 #endif