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
Plunger/tcd1103Sensor.h@100:1ff35c07217c, 2019-11-28 (annotated)
- Committer:
- mjr
- Date:
- Thu Nov 28 23:18:23 2019 +0000
- Revision:
- 100:1ff35c07217c
- Child:
- 101:755f44622abc
Added preliminary support for AEAT-6012 and TCD1103 sensors; use continuous averaging for pot sensor analog in; more AltAnalogIn options for timing and resolution
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mjr | 100:1ff35c07217c | 1 | // Toshiba TCD1103 linear image sensors |
mjr | 100:1ff35c07217c | 2 | // |
mjr | 100:1ff35c07217c | 3 | // This sensor is similar to the original TSL1410R in both its electronic |
mjr | 100:1ff35c07217c | 4 | // interface and the theory of operation. The details of the electronics |
mjr | 100:1ff35c07217c | 5 | // are different enough that we can't reuse the same code at the hardware |
mjr | 100:1ff35c07217c | 6 | // interface level, but the principle of operation is similar: the sensor |
mjr | 100:1ff35c07217c | 7 | // provides a serial interface to a file of pixels transferred as analog |
mjr | 100:1ff35c07217c | 8 | // voltage levels representing the charge collected. |
mjr | 100:1ff35c07217c | 9 | // |
mjr | 100:1ff35c07217c | 10 | // As with the TSL1410R, we position the sensor so that the pixel row is |
mjr | 100:1ff35c07217c | 11 | // aligned with the plunger axis, with a backlight, and we detect the plunger |
mjr | 100:1ff35c07217c | 12 | // position by looking for an edge between a light area (where the backlight |
mjr | 100:1ff35c07217c | 13 | // is unobstructed) and a dark area (where the plunger rod is blocking the |
mjr | 100:1ff35c07217c | 14 | // backlight). The optical sensor area of the TSL1410R is large enough to |
mjr | 100:1ff35c07217c | 15 | // cover the entire plunger travel distance, so the physical setup for that |
mjr | 100:1ff35c07217c | 16 | // sensor is a simple matter of placing the sensor near the plunger, so that |
mjr | 100:1ff35c07217c | 17 | // the plunger casts a shadow on the sensor. The TCD1103, in contrast, has a |
mjr | 100:1ff35c07217c | 18 | // small optical sensor area, about 8mm long, so in this case we have to use |
mjr | 100:1ff35c07217c | 19 | // a lens to reduce the image of the plunger by about 10X (from the 80mm |
mjr | 100:1ff35c07217c | 20 | // plunger travel distance to the 8mm sensor size). This makes the physical |
mjr | 100:1ff35c07217c | 21 | // setup more complex, but it has the advantage of giving us a focused image, |
mjr | 100:1ff35c07217c | 22 | // allowing for better precision in detecting the edge. With the unfocused |
mjr | 100:1ff35c07217c | 23 | // image used in the TSL1410R setup, the shadow was blurry over about 1/50". |
mjr | 100:1ff35c07217c | 24 | // With a lens to focus the image, we could potentially get as good as |
mjr | 100:1ff35c07217c | 25 | // single-pixel resolution, which would give us about 1/500" resolution on |
mjr | 100:1ff35c07217c | 26 | // this 1500-pixel sensor. |
mjr | 100:1ff35c07217c | 27 | // |
mjr | 100:1ff35c07217c | 28 | |
mjr | 100:1ff35c07217c | 29 | #include "edgeSensor.h" |
mjr | 100:1ff35c07217c | 30 | #include "TCD1103.h" |
mjr | 100:1ff35c07217c | 31 | |
mjr | 100:1ff35c07217c | 32 | template <bool invertedLogicGates> |
mjr | 100:1ff35c07217c | 33 | class PlungerSensorImageInterfaceTCD1103: public PlungerSensorImageInterface |
mjr | 100:1ff35c07217c | 34 | { |
mjr | 100:1ff35c07217c | 35 | public: |
mjr | 100:1ff35c07217c | 36 | // Note that the TCD1103 has 1500 actual image pixels, but the serial |
mjr | 100:1ff35c07217c | 37 | // interface provides 32 dummy elements on the front end (before the |
mjr | 100:1ff35c07217c | 38 | // first image pixel) and 14 dummy elements on the back end (after the |
mjr | 100:1ff35c07217c | 39 | // last image pixel), for a total of 1546 serial outputs. |
mjr | 100:1ff35c07217c | 40 | PlungerSensorImageInterfaceTCD1103(PinName fm, PinName os, PinName icg, PinName sh) |
mjr | 100:1ff35c07217c | 41 | : PlungerSensorImageInterface(1546), sensor(fm, os, icg, sh) |
mjr | 100:1ff35c07217c | 42 | { |
mjr | 100:1ff35c07217c | 43 | } |
mjr | 100:1ff35c07217c | 44 | |
mjr | 100:1ff35c07217c | 45 | // is the sensor ready? |
mjr | 100:1ff35c07217c | 46 | virtual bool ready() { return sensor.ready(); } |
mjr | 100:1ff35c07217c | 47 | |
mjr | 100:1ff35c07217c | 48 | // is a DMA transfer in progress? |
mjr | 100:1ff35c07217c | 49 | virtual bool dmaBusy() { return sensor.dmaBusy(); } |
mjr | 100:1ff35c07217c | 50 | |
mjr | 100:1ff35c07217c | 51 | virtual void init() |
mjr | 100:1ff35c07217c | 52 | { |
mjr | 100:1ff35c07217c | 53 | sensor.clear(); |
mjr | 100:1ff35c07217c | 54 | } |
mjr | 100:1ff35c07217c | 55 | |
mjr | 100:1ff35c07217c | 56 | // get the average sensor scan time |
mjr | 100:1ff35c07217c | 57 | virtual uint32_t getAvgScanTime() { return sensor.getAvgScanTime(); } |
mjr | 100:1ff35c07217c | 58 | |
mjr | 100:1ff35c07217c | 59 | protected: |
mjr | 100:1ff35c07217c | 60 | virtual void readPix(uint8_t* &pix, uint32_t &t, int axcTime) |
mjr | 100:1ff35c07217c | 61 | { |
mjr | 100:1ff35c07217c | 62 | // start reading the next pixel array (this waits for any DMA |
mjr | 100:1ff35c07217c | 63 | // transfer in progress to finish, ensuring a stable pixel buffer) |
mjr | 100:1ff35c07217c | 64 | sensor.startCapture(axcTime); |
mjr | 100:1ff35c07217c | 65 | |
mjr | 100:1ff35c07217c | 66 | // get the image array from the last capture |
mjr | 100:1ff35c07217c | 67 | sensor.getPix(pix, t); |
mjr | 100:1ff35c07217c | 68 | } |
mjr | 100:1ff35c07217c | 69 | |
mjr | 100:1ff35c07217c | 70 | virtual void getStatusReportPixels( |
mjr | 100:1ff35c07217c | 71 | uint8_t* &pix, uint32_t &t, int axcTime, int extraTime) |
mjr | 100:1ff35c07217c | 72 | { |
mjr | 100:1ff35c07217c | 73 | // The sensor's internal buffering scheme makes it a little tricky |
mjr | 100:1ff35c07217c | 74 | // to get the requested timing, and our own double-buffering adds a |
mjr | 100:1ff35c07217c | 75 | // little complexity as well. To get the exact timing requested, we |
mjr | 100:1ff35c07217c | 76 | // have to work with the buffering pipeline like so: |
mjr | 100:1ff35c07217c | 77 | // |
mjr | 100:1ff35c07217c | 78 | // 1. Call startCapture(). This waits for any in-progress pixel |
mjr | 100:1ff35c07217c | 79 | // transfer from the sensor to finish, then executes an SH/ICG pulse |
mjr | 100:1ff35c07217c | 80 | // on the sensor. The pulse takes a snapshot of the current live |
mjr | 100:1ff35c07217c | 81 | // photo receptors to the sensor shift register. These pixels have |
mjr | 100:1ff35c07217c | 82 | // been integrating starting from before we were called; call this |
mjr | 100:1ff35c07217c | 83 | // integration period A. So the shift register contains period A. |
mjr | 100:1ff35c07217c | 84 | // The SH/ICG then grounds the photo receptors, clearing their |
mjr | 100:1ff35c07217c | 85 | // charge, thus starting a new integration period B. After sending |
mjr | 100:1ff35c07217c | 86 | // the SH/ICG pulse, startCapture() begins a DMA transfer of the |
mjr | 100:1ff35c07217c | 87 | // shift register pixels (period A) to one of our two buffers (call |
mjr | 100:1ff35c07217c | 88 | // it the EVEN buffer). |
mjr | 100:1ff35c07217c | 89 | // |
mjr | 100:1ff35c07217c | 90 | // 2. Wait for the current transfer (period A to the EVEN buffer) |
mjr | 100:1ff35c07217c | 91 | // to finish. The minimum integration time is the time of one |
mjr | 100:1ff35c07217c | 92 | // transfer cycle, so this brings us to the minimum time for |
mjr | 100:1ff35c07217c | 93 | // period B. |
mjr | 100:1ff35c07217c | 94 | // |
mjr | 100:1ff35c07217c | 95 | // 3. Now pause for the requested extra delay time. Period B is |
mjr | 100:1ff35c07217c | 96 | // still running at this point (it keeps going until we start a |
mjr | 100:1ff35c07217c | 97 | // new capture), so this pause adds the requested extra time to |
mjr | 100:1ff35c07217c | 98 | // period B's total integration time. This brings period B to |
mjr | 100:1ff35c07217c | 99 | // exactly the requested total time. |
mjr | 100:1ff35c07217c | 100 | // |
mjr | 100:1ff35c07217c | 101 | // 4. Call startCapture() to end period B, move period B's pixels |
mjr | 100:1ff35c07217c | 102 | // to the sensor's shift register, and begin period C. This |
mjr | 100:1ff35c07217c | 103 | // switches DMA buffers, so the EVEN buffer (with period A) is now |
mjr | 100:1ff35c07217c | 104 | // available, and the ODD buffer becomes the DMA target for the |
mjr | 100:1ff35c07217c | 105 | // period B pixels. |
mjr | 100:1ff35c07217c | 106 | // |
mjr | 100:1ff35c07217c | 107 | // 5. Wait for the period B pixels to become available, via |
mjr | 100:1ff35c07217c | 108 | // waitPix(). This waits for the DMA transfer to complete and |
mjr | 100:1ff35c07217c | 109 | // hands us the latest (ODD) transfer buffer. |
mjr | 100:1ff35c07217c | 110 | // |
mjr | 100:1ff35c07217c | 111 | sensor.startCapture(axcTime); // begin transfer of pixels from incoming period A, begin integration period B |
mjr | 100:1ff35c07217c | 112 | sensor.wait(); // wait for scan of A to complete, as minimum integration B time |
mjr | 100:1ff35c07217c | 113 | wait_us(long(extraTime) * 100); // add extraTime (0.1ms == 100us increments) to integration B time |
mjr | 100:1ff35c07217c | 114 | sensor.startCapture(axcTime); // begin transfer of pixels from integration period B, begin period C; period A pixels now available |
mjr | 100:1ff35c07217c | 115 | |
mjr | 100:1ff35c07217c | 116 | // wait for the DMA transfer of period B to finish, and get the |
mjr | 100:1ff35c07217c | 117 | // period B pixels |
mjr | 100:1ff35c07217c | 118 | sensor.waitPix(pix, t); |
mjr | 100:1ff35c07217c | 119 | } |
mjr | 100:1ff35c07217c | 120 | |
mjr | 100:1ff35c07217c | 121 | // reset after a status report |
mjr | 100:1ff35c07217c | 122 | virtual void resetAfterStatusReport(int axcTime) |
mjr | 100:1ff35c07217c | 123 | { |
mjr | 100:1ff35c07217c | 124 | // It takes us a while to send all of the pixels, since we have |
mjr | 100:1ff35c07217c | 125 | // to break them up into many USB reports. This delay means that |
mjr | 100:1ff35c07217c | 126 | // the sensor has been sitting there integrating for much longer |
mjr | 100:1ff35c07217c | 127 | // than usual, so the next frame read will be overexposed. To |
mjr | 100:1ff35c07217c | 128 | // mitigate this, make sure we don't have a capture running, |
mjr | 100:1ff35c07217c | 129 | // then clear the sensor and start a new capture. |
mjr | 100:1ff35c07217c | 130 | sensor.wait(); |
mjr | 100:1ff35c07217c | 131 | sensor.clear(); |
mjr | 100:1ff35c07217c | 132 | sensor.startCapture(axcTime); |
mjr | 100:1ff35c07217c | 133 | } |
mjr | 100:1ff35c07217c | 134 | |
mjr | 100:1ff35c07217c | 135 | // the low-level interface to the TSL14xx sensor |
mjr | 100:1ff35c07217c | 136 | TCD1103<invertedLogicGates> sensor; |
mjr | 100:1ff35c07217c | 137 | }; |
mjr | 100:1ff35c07217c | 138 | |
mjr | 100:1ff35c07217c | 139 | template<bool invertedLogicGates> |
mjr | 100:1ff35c07217c | 140 | class PlungerSensorTCD1103: public PlungerSensorEdgePos |
mjr | 100:1ff35c07217c | 141 | { |
mjr | 100:1ff35c07217c | 142 | public: |
mjr | 100:1ff35c07217c | 143 | // Note that the TCD1103 has 1500 actual image pixels, but the serial |
mjr | 100:1ff35c07217c | 144 | // interface provides 32 dummy elements on the front end (before the |
mjr | 100:1ff35c07217c | 145 | // first image pixel) and 14 dummy elements on the back end (after the |
mjr | 100:1ff35c07217c | 146 | // last image pixel), for a total of 1546 serial outputs. |
mjr | 100:1ff35c07217c | 147 | PlungerSensorTCD1103(PinName fm, PinName os, PinName icg, PinName sh) |
mjr | 100:1ff35c07217c | 148 | : PlungerSensorEdgePos(sensor, 1546), sensor(fm, os, icg, sh) |
mjr | 100:1ff35c07217c | 149 | { |
mjr | 100:1ff35c07217c | 150 | } |
mjr | 100:1ff35c07217c | 151 | |
mjr | 100:1ff35c07217c | 152 | protected: |
mjr | 100:1ff35c07217c | 153 | PlungerSensorImageInterfaceTCD1103<invertedLogicGates> sensor; |
mjr | 100:1ff35c07217c | 154 | }; |