Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed FastIO FastPWM USBDevice
Fork of Pinscape_Controller by
Plunger/barCodeSensor.h@82:4f6209cb5c33, 2017-04-13 (annotated)
- Committer:
- mjr
- Date:
- Thu Apr 13 23:20:28 2017 +0000
- Revision:
- 82:4f6209cb5c33
- Child:
- 86:e30a1f60f783
Plunger refactoring; AEDR-8300 added; TSL1401CL in progress; VL6180X added
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mjr | 82:4f6209cb5c33 | 1 | // Plunger sensor type for bar-code based absolute position encoders. |
mjr | 82:4f6209cb5c33 | 2 | // This type of sensor uses an optical sensor that moves with the plunger |
mjr | 82:4f6209cb5c33 | 3 | // along a guide rail with printed bar codes along its length that encode |
mjr | 82:4f6209cb5c33 | 4 | // the absolute position at each point. We figure the plunger position |
mjr | 82:4f6209cb5c33 | 5 | // by reading the bar code and decoding it into a position figure. |
mjr | 82:4f6209cb5c33 | 6 | // |
mjr | 82:4f6209cb5c33 | 7 | // The bar code has to be encoded in a specific format that we recognize. |
mjr | 82:4f6209cb5c33 | 8 | // We use a 10-bit reflected Gray code, optically encoded using a Manchester- |
mjr | 82:4f6209cb5c33 | 9 | // type of coding. Each bit is represented as a fixed-width area on the |
mjr | 82:4f6209cb5c33 | 10 | // bar, half white and half black. The bit value is encoded in the order |
mjr | 82:4f6209cb5c33 | 11 | // of the colors: Black/White is '0', and White/Black is '1'. |
mjr | 82:4f6209cb5c33 | 12 | // |
mjr | 82:4f6209cb5c33 | 13 | // Gray codes are ideal for this type of application, because they have the |
mjr | 82:4f6209cb5c33 | 14 | // property that any two adjacent code values differ in exactly one bit. |
mjr | 82:4f6209cb5c33 | 15 | // This is perfectly suited to an optical sensor scanning a moving target. |
mjr | 82:4f6209cb5c33 | 16 | // For one thing, if we're halfway between two positions, the single-bit |
mjr | 82:4f6209cb5c33 | 17 | // difference between adjacent codes means that exactly one bit will be |
mjr | 82:4f6209cb5c33 | 18 | // ambiguous, so even if we get it wrong because of the ambiguous optical |
mjr | 82:4f6209cb5c33 | 19 | // data, we'll still be +/- 1 position from the true position. The other |
mjr | 82:4f6209cb5c33 | 20 | // good feature is that any motion blur in images taken during rapid motion |
mjr | 82:4f6209cb5c33 | 21 | // will likewise create ambiguity in the least significant bits, so we'll |
mjr | 82:4f6209cb5c33 | 22 | // gracefully lose precision as motion blur increases but still have the |
mjr | 82:4f6209cb5c33 | 23 | // correct values for the most significant bits, which is to say that we'll |
mjr | 82:4f6209cb5c33 | 24 | // know our true position at reduced precision during motion. |
mjr | 82:4f6209cb5c33 | 25 | // |
mjr | 82:4f6209cb5c33 | 26 | // We use the Manchester-type optical coding because it has good properties |
mjr | 82:4f6209cb5c33 | 27 | // for noisy images. In particular, we evaluate each bit based only on |
mjr | 82:4f6209cb5c33 | 28 | // the light levels of nearby pixels. This insulates us from non-uniformity |
mjr | 82:4f6209cb5c33 | 29 | // in the light level across the image. We don't have to care if the pixels |
mjr | 82:4f6209cb5c33 | 30 | // in a bit are above or below the average or median across the whole image; |
mjr | 82:4f6209cb5c33 | 31 | // we only have to compare them to the immediately adjacent few pixels. |
mjr | 82:4f6209cb5c33 | 32 | // This gives us highly stable readings even with poor lighting conditions. |
mjr | 82:4f6209cb5c33 | 33 | // That's desirable because it simplifies the requirements for the physical |
mjr | 82:4f6209cb5c33 | 34 | // sensor installation. |
mjr | 82:4f6209cb5c33 | 35 | // |
mjr | 82:4f6209cb5c33 | 36 | |
mjr | 82:4f6209cb5c33 | 37 | #ifndef _BARCODESENSOR_H_ |
mjr | 82:4f6209cb5c33 | 38 | #define _BARCODESENSOR_H_ |
mjr | 82:4f6209cb5c33 | 39 | |
mjr | 82:4f6209cb5c33 | 40 | #include "plunger.h" |
mjr | 82:4f6209cb5c33 | 41 | #include "tsl14xxSensor.h" |
mjr | 82:4f6209cb5c33 | 42 | |
mjr | 82:4f6209cb5c33 | 43 | // Base class for bar-code sensors |
mjr | 82:4f6209cb5c33 | 44 | class PlungerSensorBarCode |
mjr | 82:4f6209cb5c33 | 45 | { |
mjr | 82:4f6209cb5c33 | 46 | public: |
mjr | 82:4f6209cb5c33 | 47 | bool process(const uint8_t *pix, int npix, int &pos) |
mjr | 82:4f6209cb5c33 | 48 | { |
mjr | 82:4f6209cb5c33 | 49 | // $$$ to be written |
mjr | 82:4f6209cb5c33 | 50 | return false; |
mjr | 82:4f6209cb5c33 | 51 | } |
mjr | 82:4f6209cb5c33 | 52 | }; |
mjr | 82:4f6209cb5c33 | 53 | |
mjr | 82:4f6209cb5c33 | 54 | // PlungerSensor interface implementation for edge detection setups |
mjr | 82:4f6209cb5c33 | 55 | class PlungerSensorBarCodeTSL14xx: public PlungerSensorTSL14xx, public PlungerSensorBarCode |
mjr | 82:4f6209cb5c33 | 56 | { |
mjr | 82:4f6209cb5c33 | 57 | public: |
mjr | 82:4f6209cb5c33 | 58 | PlungerSensorBarCodeTSL14xx(int nativePix, PinName si, PinName clock, PinName ao) |
mjr | 82:4f6209cb5c33 | 59 | : PlungerSensorTSL14xx(nativePix, si, clock, ao), |
mjr | 82:4f6209cb5c33 | 60 | PlungerSensorBarCode() |
mjr | 82:4f6209cb5c33 | 61 | { |
mjr | 82:4f6209cb5c33 | 62 | } |
mjr | 82:4f6209cb5c33 | 63 | |
mjr | 82:4f6209cb5c33 | 64 | protected: |
mjr | 82:4f6209cb5c33 | 65 | // process the image through the bar code reader |
mjr | 82:4f6209cb5c33 | 66 | virtual bool process(const uint8_t *pix, int npix, int &pos) |
mjr | 82:4f6209cb5c33 | 67 | { |
mjr | 82:4f6209cb5c33 | 68 | // adjust the exposure |
mjr | 82:4f6209cb5c33 | 69 | adjustExposure(pix, npix); |
mjr | 82:4f6209cb5c33 | 70 | |
mjr | 82:4f6209cb5c33 | 71 | // do the standard bar code processing |
mjr | 82:4f6209cb5c33 | 72 | return PlungerSensorBarCode::process(pix, npix, pos); |
mjr | 82:4f6209cb5c33 | 73 | } |
mjr | 82:4f6209cb5c33 | 74 | |
mjr | 82:4f6209cb5c33 | 75 | // adjust the exposure |
mjr | 82:4f6209cb5c33 | 76 | void adjustExposure(const uint8_t *pix, int npix) |
mjr | 82:4f6209cb5c33 | 77 | { |
mjr | 82:4f6209cb5c33 | 78 | // Count the number of pixels near total darkness and |
mjr | 82:4f6209cb5c33 | 79 | // total saturation |
mjr | 82:4f6209cb5c33 | 80 | int nDark = 0, nSat = 0; |
mjr | 82:4f6209cb5c33 | 81 | for (int i = 0 ; i < npix ; ++i) |
mjr | 82:4f6209cb5c33 | 82 | { |
mjr | 82:4f6209cb5c33 | 83 | int pi = pix[i]; |
mjr | 82:4f6209cb5c33 | 84 | if (pi < 10) |
mjr | 82:4f6209cb5c33 | 85 | ++nDark; |
mjr | 82:4f6209cb5c33 | 86 | else if (pi > 244) |
mjr | 82:4f6209cb5c33 | 87 | ++nSat; |
mjr | 82:4f6209cb5c33 | 88 | } |
mjr | 82:4f6209cb5c33 | 89 | |
mjr | 82:4f6209cb5c33 | 90 | // If more than 30% of pixels are near total darkness, increase |
mjr | 82:4f6209cb5c33 | 91 | // the exposure time. If more than 30% are near total saturation, |
mjr | 82:4f6209cb5c33 | 92 | // decrease the exposure time. |
mjr | 82:4f6209cb5c33 | 93 | int pct30 = uint32_t(npix * 19661) >> 16; |
mjr | 82:4f6209cb5c33 | 94 | int pct50 = uint32_t(npix) >> 1; |
mjr | 82:4f6209cb5c33 | 95 | if (nDark > pct50 && nSat < pct30) |
mjr | 82:4f6209cb5c33 | 96 | { |
mjr | 82:4f6209cb5c33 | 97 | // very dark - increase exposure time a lot |
mjr | 82:4f6209cb5c33 | 98 | if (axcTime < 450) |
mjr | 82:4f6209cb5c33 | 99 | axcTime += 50; |
mjr | 82:4f6209cb5c33 | 100 | } |
mjr | 82:4f6209cb5c33 | 101 | else if (nDark > pct30 && nSat < pct30) |
mjr | 82:4f6209cb5c33 | 102 | { |
mjr | 82:4f6209cb5c33 | 103 | // dark - increase exposure time a bit |
mjr | 82:4f6209cb5c33 | 104 | if (axcTime < 490) |
mjr | 82:4f6209cb5c33 | 105 | axcTime += 10; |
mjr | 82:4f6209cb5c33 | 106 | } |
mjr | 82:4f6209cb5c33 | 107 | else if (nSat > pct50 && nDark < pct30) |
mjr | 82:4f6209cb5c33 | 108 | { |
mjr | 82:4f6209cb5c33 | 109 | // very overexposed - decrease exposure time a lot |
mjr | 82:4f6209cb5c33 | 110 | if (axcTime > 50) |
mjr | 82:4f6209cb5c33 | 111 | axcTime -= 50; |
mjr | 82:4f6209cb5c33 | 112 | else |
mjr | 82:4f6209cb5c33 | 113 | axcTime = 0; |
mjr | 82:4f6209cb5c33 | 114 | } |
mjr | 82:4f6209cb5c33 | 115 | else if (nSat > pct30 && nDark < pct30) |
mjr | 82:4f6209cb5c33 | 116 | { |
mjr | 82:4f6209cb5c33 | 117 | // overexposed - decrease exposure time a little |
mjr | 82:4f6209cb5c33 | 118 | if (axcTime > 10) |
mjr | 82:4f6209cb5c33 | 119 | axcTime -= 10; |
mjr | 82:4f6209cb5c33 | 120 | else |
mjr | 82:4f6209cb5c33 | 121 | axcTime = 0; |
mjr | 82:4f6209cb5c33 | 122 | } |
mjr | 82:4f6209cb5c33 | 123 | } |
mjr | 82:4f6209cb5c33 | 124 | }; |
mjr | 82:4f6209cb5c33 | 125 | |
mjr | 82:4f6209cb5c33 | 126 | |
mjr | 82:4f6209cb5c33 | 127 | // TSL1401CL |
mjr | 82:4f6209cb5c33 | 128 | class PlungerSensorTSL1401CL: public PlungerSensorBarCodeTSL14xx |
mjr | 82:4f6209cb5c33 | 129 | { |
mjr | 82:4f6209cb5c33 | 130 | public: |
mjr | 82:4f6209cb5c33 | 131 | PlungerSensorTSL1401CL(PinName si, PinName clock, PinName a0) |
mjr | 82:4f6209cb5c33 | 132 | : PlungerSensorBarCodeTSL14xx(128, si, clock, a0) |
mjr | 82:4f6209cb5c33 | 133 | { |
mjr | 82:4f6209cb5c33 | 134 | } |
mjr | 82:4f6209cb5c33 | 135 | }; |
mjr | 82:4f6209cb5c33 | 136 | |
mjr | 82:4f6209cb5c33 | 137 | #endif |