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.
Fork of scoreLight_Advanced by
hardwareIO/hardwareIO.cpp@34:1244fa3f2559, 2012-11-07 (annotated)
- Committer:
- mbedalvaro
- Date:
- Wed Nov 07 14:41:55 2012 +0000
- Revision:
- 34:1244fa3f2559
- Parent:
- 31:5f039cbddee8
- Child:
- 35:35af5086ab4f
added hardware button & potentiometer to select the thresholding mode and parameters. Problems with the ADC conversion though...
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mbedalvaro | 31:5f039cbddee8 | 1 | #include "hardwareIO.h" |
mbedalvaro | 31:5f039cbddee8 | 2 | |
mbedalvaro | 31:5f039cbddee8 | 3 | HardwareIO IO; // preintantiation of cross-file global object IO |
mbedalvaro | 31:5f039cbddee8 | 4 | |
mbedalvaro | 31:5f039cbddee8 | 5 | // -------------------------------------- (0) SETUP ALL IO (call this in the setup() function in main program) |
mbedalvaro | 31:5f039cbddee8 | 6 | |
mbedalvaro | 31:5f039cbddee8 | 7 | Serial pc(USBTX, USBRX); // tx, rx |
mbedalvaro | 31:5f039cbddee8 | 8 | LocalFileSystem local("local"); // Create the local filesystem under the name "local" |
mbedalvaro | 31:5f039cbddee8 | 9 | |
mbedalvaro | 31:5f039cbddee8 | 10 | SPI spiDAC(MOSI_PIN, MISO_PIN, SCK_PIN); // mosi, miso, sclk |
mbedalvaro | 31:5f039cbddee8 | 11 | DigitalOut csDAC(CS_DAC_MIRRORS); |
mbedalvaro | 34:1244fa3f2559 | 12 | |
mbedalvaro | 31:5f039cbddee8 | 13 | DigitalOut Laser_Red(LASER_RED_PIN); // NOTE: this is NOT the lock in sensing laser (actually, not used yet) |
mbedalvaro | 31:5f039cbddee8 | 14 | DigitalOut Laser_Green(LASER_GREEN_PIN); |
mbedalvaro | 31:5f039cbddee8 | 15 | DigitalOut Laser_Blue(LASER_BLUE_PIN); |
mbedalvaro | 34:1244fa3f2559 | 16 | |
mbedalvaro | 34:1244fa3f2559 | 17 | // Some manual controls over the hardware function: |
mbedalvaro | 34:1244fa3f2559 | 18 | InterruptIn switchOne(SWITCH_ONE); |
mbedalvaro | 34:1244fa3f2559 | 19 | DigitalOut ledSwitchOne(LED_SWITCH_ONE); |
mbedalvaro | 34:1244fa3f2559 | 20 | InterruptIn switchTwo(SWITCH_TWO); |
mbedalvaro | 34:1244fa3f2559 | 21 | //AnalogIn ain(POT_ANALOG_INPUT); |
mbedalvaro | 31:5f039cbddee8 | 22 | |
mbedalvaro | 31:5f039cbddee8 | 23 | void HardwareIO::init(void) { |
mbedalvaro | 34:1244fa3f2559 | 24 | |
mbedalvaro | 34:1244fa3f2559 | 25 | // Set laser powers down: |
mbedalvaro | 34:1244fa3f2559 | 26 | setRedPower(0);// TTL red laser (not used - actually not present) |
mbedalvaro | 34:1244fa3f2559 | 27 | setGreenPower(0); |
mbedalvaro | 34:1244fa3f2559 | 28 | setBluePower(0); |
mbedalvaro | 31:5f039cbddee8 | 29 | |
mbedalvaro | 31:5f039cbddee8 | 30 | //Serial Communication setup: |
mbedalvaro | 31:5f039cbddee8 | 31 | pc.baud(115200);// |
mbedalvaro | 31:5f039cbddee8 | 32 | // pc.baud(921600);//115200);// |
mbedalvaro | 31:5f039cbddee8 | 33 | |
mbedalvaro | 31:5f039cbddee8 | 34 | // Setup for lock-in amplifier and pwm references: |
mbedalvaro | 34:1244fa3f2559 | 35 | setLaserLockinPower(1);// actually this is the Red laser in the hardware |
mbedalvaro | 31:5f039cbddee8 | 36 | lockin.init(); |
mbedalvaro | 31:5f039cbddee8 | 37 | |
mbedalvaro | 34:1244fa3f2559 | 38 | // Setup for DAC control to move the mirrors: |
mbedalvaro | 34:1244fa3f2559 | 39 | // Set spi for 8 bit data, high steady state clock, |
mbedalvaro | 34:1244fa3f2559 | 40 | // second edge capture, with a 10MHz clock rate: |
mbedalvaro | 31:5f039cbddee8 | 41 | csDAC = 1; |
mbedalvaro | 31:5f039cbddee8 | 42 | spiDAC.format(16,0); |
mbedalvaro | 31:5f039cbddee8 | 43 | spiDAC.frequency(16000000); |
mbedalvaro | 31:5f039cbddee8 | 44 | |
mbedalvaro | 31:5f039cbddee8 | 45 | // default initial mirror position: |
mbedalvaro | 31:5f039cbddee8 | 46 | writeOutX(CENTER_AD_MIRROR_X); |
mbedalvaro | 31:5f039cbddee8 | 47 | writeOutY(CENTER_AD_MIRROR_Y); |
mbedalvaro | 31:5f039cbddee8 | 48 | |
mbedalvaro | 31:5f039cbddee8 | 49 | // Load LUT table: |
mbedalvaro | 31:5f039cbddee8 | 50 | setLUT(); |
mbedalvaro | 34:1244fa3f2559 | 51 | |
mbedalvaro | 34:1244fa3f2559 | 52 | // Set interrupts on RAISING edge for button-switch functions: |
mbedalvaro | 34:1244fa3f2559 | 53 | // Note: The pin input will be logic '0' for any voltage on the pin below 0.8v, and '1' for any voltage above 2.0v. |
mbedalvaro | 34:1244fa3f2559 | 54 | // By default, the InterruptIn is setup with an internal pull-down resistor, but for security and clarity I will do it explicitly here: |
mbedalvaro | 34:1244fa3f2559 | 55 | switchOne.mode(PullUp); // pull down seems not very good |
mbedalvaro | 34:1244fa3f2559 | 56 | switchTwo.mode(PullUp); |
mbedalvaro | 34:1244fa3f2559 | 57 | switchOne.fall(this, &HardwareIO::switchOneInterrupt); // attach the address of the flip function to the falling edge |
mbedalvaro | 34:1244fa3f2559 | 58 | switchTwo.fall(this, &HardwareIO::switchTwoInterrupt); // attach the address of the flip function to the falling edge |
mbedalvaro | 34:1244fa3f2559 | 59 | switchOneState=false; // false means fixed threshold |
mbedalvaro | 34:1244fa3f2559 | 60 | switchTwoState=false; |
mbedalvaro | 34:1244fa3f2559 | 61 | switchOneChange=false; |
mbedalvaro | 34:1244fa3f2559 | 62 | switchTwoChange=false; |
mbedalvaro | 34:1244fa3f2559 | 63 | ledSwitchOne=(switchOneState? 1 :0); |
mbedalvaro | 34:1244fa3f2559 | 64 | |
mbedalvaro | 34:1244fa3f2559 | 65 | // Read and update pot value: |
mbedalvaro | 34:1244fa3f2559 | 66 | // updatePotValue(); // the value will be ajusted in the range 0-255 |
mbedalvaro | 34:1244fa3f2559 | 67 | } |
mbedalvaro | 34:1244fa3f2559 | 68 | |
mbedalvaro | 34:1244fa3f2559 | 69 | // these ISR could do more (like debouncing). |
mbedalvaro | 34:1244fa3f2559 | 70 | // For the time being, I will debounce electrically with a small capacitor. |
mbedalvaro | 34:1244fa3f2559 | 71 | void HardwareIO::switchOneInterrupt() { |
mbedalvaro | 34:1244fa3f2559 | 72 | switchOneState=!switchOneState; |
mbedalvaro | 34:1244fa3f2559 | 73 | ledSwitchOne=(switchOneState? 1 :0); // this switch has a built-in led |
mbedalvaro | 34:1244fa3f2559 | 74 | switchOneChange=true; |
mbedalvaro | 34:1244fa3f2559 | 75 | } |
mbedalvaro | 34:1244fa3f2559 | 76 | void HardwareIO::switchTwoInterrupt() { |
mbedalvaro | 34:1244fa3f2559 | 77 | switchTwoState=!switchTwoState; |
mbedalvaro | 34:1244fa3f2559 | 78 | switchTwoChange=true; |
mbedalvaro | 34:1244fa3f2559 | 79 | } |
mbedalvaro | 34:1244fa3f2559 | 80 | |
mbedalvaro | 34:1244fa3f2559 | 81 | bool HardwareIO::switchOneCheck(bool& state) { |
mbedalvaro | 34:1244fa3f2559 | 82 | if (switchOneChange) { |
mbedalvaro | 34:1244fa3f2559 | 83 | switchOneChange=false; |
mbedalvaro | 34:1244fa3f2559 | 84 | state=switchOneState; |
mbedalvaro | 34:1244fa3f2559 | 85 | return(true); |
mbedalvaro | 34:1244fa3f2559 | 86 | } else |
mbedalvaro | 34:1244fa3f2559 | 87 | return(false); |
mbedalvaro | 34:1244fa3f2559 | 88 | } |
mbedalvaro | 34:1244fa3f2559 | 89 | |
mbedalvaro | 34:1244fa3f2559 | 90 | bool HardwareIO::switchTwoCheck(bool& state) { |
mbedalvaro | 34:1244fa3f2559 | 91 | if (switchTwoChange) { |
mbedalvaro | 34:1244fa3f2559 | 92 | switchTwoChange=false; |
mbedalvaro | 34:1244fa3f2559 | 93 | state=switchTwoState; |
mbedalvaro | 34:1244fa3f2559 | 94 | return(true); |
mbedalvaro | 34:1244fa3f2559 | 95 | } else return(false); |
mbedalvaro | 34:1244fa3f2559 | 96 | } |
mbedalvaro | 34:1244fa3f2559 | 97 | |
mbedalvaro | 34:1244fa3f2559 | 98 | unsigned char HardwareIO::updatePotValue() { // this will update the pot value, and return it too. |
mbedalvaro | 34:1244fa3f2559 | 99 | //The value will be ajusted in the range 0-255 |
mbedalvaro | 34:1244fa3f2559 | 100 | //The 0.0v to 3.3v range of the AnalogIn is represented in software as a normalised floating point number from 0.0 to 1.0. |
mbedalvaro | 34:1244fa3f2559 | 101 | //potValue=(unsigned char )(ain*255); |
mbedalvaro | 34:1244fa3f2559 | 102 | |
mbedalvaro | 34:1244fa3f2559 | 103 | lockin.setADC_forLockin(0); |
mbedalvaro | 34:1244fa3f2559 | 104 | |
mbedalvaro | 34:1244fa3f2559 | 105 | adc.setup(POT_ANALOG_INPUT,1); |
mbedalvaro | 34:1244fa3f2559 | 106 | wait(1); |
mbedalvaro | 34:1244fa3f2559 | 107 | |
mbedalvaro | 34:1244fa3f2559 | 108 | //Measure pin POT_ANALOG_INPUT |
mbedalvaro | 34:1244fa3f2559 | 109 | adc.select(POT_ANALOG_INPUT); |
mbedalvaro | 34:1244fa3f2559 | 110 | //Start ADC conversion |
mbedalvaro | 34:1244fa3f2559 | 111 | adc.start(); |
mbedalvaro | 34:1244fa3f2559 | 112 | //Wait for it to complete |
mbedalvaro | 34:1244fa3f2559 | 113 | while(!adc.done(POT_ANALOG_INPUT)); |
mbedalvaro | 34:1244fa3f2559 | 114 | potValue=adc.read(POT_ANALOG_INPUT); |
mbedalvaro | 34:1244fa3f2559 | 115 | |
mbedalvaro | 34:1244fa3f2559 | 116 | //Unset pin POT_ANALOG_INPUT |
mbedalvaro | 34:1244fa3f2559 | 117 | adc.setup(POT_ANALOG_INPUT,0); |
mbedalvaro | 34:1244fa3f2559 | 118 | |
mbedalvaro | 34:1244fa3f2559 | 119 | lockin.setADC_forLockin(1); |
mbedalvaro | 34:1244fa3f2559 | 120 | |
mbedalvaro | 34:1244fa3f2559 | 121 | return(potValue); |
mbedalvaro | 31:5f039cbddee8 | 122 | } |
mbedalvaro | 31:5f039cbddee8 | 123 | |
mbedalvaro | 31:5f039cbddee8 | 124 | //write on the first DAC, output A (mirror X) |
mbedalvaro | 31:5f039cbddee8 | 125 | void HardwareIO::writeOutX(unsigned short value){ |
mbedalvaro | 31:5f039cbddee8 | 126 | if(value > MAX_AD_MIRRORS) value = MAX_AD_MIRRORS; |
mbedalvaro | 31:5f039cbddee8 | 127 | if(value < MIN_AD_MIRRORS) value = MIN_AD_MIRRORS; |
mbedalvaro | 31:5f039cbddee8 | 128 | |
mbedalvaro | 31:5f039cbddee8 | 129 | value |= 0x7000; |
mbedalvaro | 31:5f039cbddee8 | 130 | value &= 0x7FFF; |
mbedalvaro | 31:5f039cbddee8 | 131 | |
mbedalvaro | 31:5f039cbddee8 | 132 | csDAC = 0; |
mbedalvaro | 31:5f039cbddee8 | 133 | spiDAC.write(value); |
mbedalvaro | 31:5f039cbddee8 | 134 | csDAC = 1; |
mbedalvaro | 31:5f039cbddee8 | 135 | } |
mbedalvaro | 31:5f039cbddee8 | 136 | |
mbedalvaro | 31:5f039cbddee8 | 137 | //write on the first DAC, output B (mirror Y) |
mbedalvaro | 31:5f039cbddee8 | 138 | void HardwareIO::writeOutY(unsigned short value){ |
mbedalvaro | 31:5f039cbddee8 | 139 | if(value > MAX_AD_MIRRORS) value = MAX_AD_MIRRORS; |
mbedalvaro | 31:5f039cbddee8 | 140 | if(value < MIN_AD_MIRRORS) value = MIN_AD_MIRRORS; |
mbedalvaro | 31:5f039cbddee8 | 141 | |
mbedalvaro | 31:5f039cbddee8 | 142 | value |= 0xF000; |
mbedalvaro | 31:5f039cbddee8 | 143 | value &= 0xFFFF; |
mbedalvaro | 31:5f039cbddee8 | 144 | |
mbedalvaro | 31:5f039cbddee8 | 145 | csDAC = 0; |
mbedalvaro | 31:5f039cbddee8 | 146 | spiDAC.write(value); |
mbedalvaro | 31:5f039cbddee8 | 147 | csDAC = 1; |
mbedalvaro | 31:5f039cbddee8 | 148 | } |
mbedalvaro | 31:5f039cbddee8 | 149 | |
mbedalvaro | 34:1244fa3f2559 | 150 | void HardwareIO::setLaserLockinPower(int powerValue){ |
mbedalvaro | 31:5f039cbddee8 | 151 | if(powerValue > 0){ |
mbedalvaro | 31:5f039cbddee8 | 152 | lockin.setLaserPower(true); |
mbedalvaro | 31:5f039cbddee8 | 153 | } |
mbedalvaro | 31:5f039cbddee8 | 154 | else{ |
mbedalvaro | 31:5f039cbddee8 | 155 | lockin.setLaserPower(false); |
mbedalvaro | 31:5f039cbddee8 | 156 | } |
mbedalvaro | 31:5f039cbddee8 | 157 | } |
mbedalvaro | 34:1244fa3f2559 | 158 | // THE TTL controlled lasers: |
mbedalvaro | 34:1244fa3f2559 | 159 | // Note: the red one is not used here |
mbedalvaro | 34:1244fa3f2559 | 160 | void HardwareIO::setRedPower(int powerValue){ |
mbedalvaro | 34:1244fa3f2559 | 161 | if(powerValue > 0){ |
mbedalvaro | 34:1244fa3f2559 | 162 | Laser_Red = 1; |
mbedalvaro | 34:1244fa3f2559 | 163 | } |
mbedalvaro | 34:1244fa3f2559 | 164 | else{ |
mbedalvaro | 34:1244fa3f2559 | 165 | Laser_Red = 0; |
mbedalvaro | 34:1244fa3f2559 | 166 | } |
mbedalvaro | 34:1244fa3f2559 | 167 | } |
mbedalvaro | 31:5f039cbddee8 | 168 | void HardwareIO::setGreenPower(int powerValue){ |
mbedalvaro | 31:5f039cbddee8 | 169 | if(powerValue > 0){ |
mbedalvaro | 31:5f039cbddee8 | 170 | Laser_Green = 1; |
mbedalvaro | 31:5f039cbddee8 | 171 | } |
mbedalvaro | 31:5f039cbddee8 | 172 | else{ |
mbedalvaro | 31:5f039cbddee8 | 173 | Laser_Green = 0; |
mbedalvaro | 31:5f039cbddee8 | 174 | } |
mbedalvaro | 31:5f039cbddee8 | 175 | } |
mbedalvaro | 31:5f039cbddee8 | 176 | void HardwareIO::setBluePower(int powerValue){ |
mbedalvaro | 31:5f039cbddee8 | 177 | if(powerValue > 0){ |
mbedalvaro | 31:5f039cbddee8 | 178 | Laser_Blue = 1; |
mbedalvaro | 31:5f039cbddee8 | 179 | } |
mbedalvaro | 31:5f039cbddee8 | 180 | else{ |
mbedalvaro | 31:5f039cbddee8 | 181 | Laser_Blue = 0; |
mbedalvaro | 31:5f039cbddee8 | 182 | } |
mbedalvaro | 31:5f039cbddee8 | 183 | } |
mbedalvaro | 31:5f039cbddee8 | 184 | |
mbedalvaro | 31:5f039cbddee8 | 185 | void HardwareIO::setRGBPower(unsigned char color) { |
mbedalvaro | 34:1244fa3f2559 | 186 | lockin.setLaserPower((color&0x04)>0? true : false); // NOTE: here the "red" is the lockin laser, not the TTL one (not used yet) |
mbedalvaro | 31:5f039cbddee8 | 187 | Laser_Green=(color&0x02)>>1; |
mbedalvaro | 31:5f039cbddee8 | 188 | Laser_Blue =color&0x01; |
mbedalvaro | 31:5f039cbddee8 | 189 | } |
mbedalvaro | 31:5f039cbddee8 | 190 | |
mbedalvaro | 31:5f039cbddee8 | 191 | void HardwareIO::showLimitsMirrors(int times) { |
mbedalvaro | 31:5f039cbddee8 | 192 | unsigned short pointsPerLine=150; |
mbedalvaro | 31:5f039cbddee8 | 193 | int shiftX = (MAX_AD_MIRRORS - MIN_AD_MIRRORS) / pointsPerLine; |
mbedalvaro | 31:5f039cbddee8 | 194 | int shiftY = (MAX_AD_MIRRORS - MIN_AD_MIRRORS) / pointsPerLine; |
mbedalvaro | 31:5f039cbddee8 | 195 | |
mbedalvaro | 31:5f039cbddee8 | 196 | Laser_Green=1; |
mbedalvaro | 31:5f039cbddee8 | 197 | |
mbedalvaro | 31:5f039cbddee8 | 198 | //for (int repeat=0; repeat<times; repeat++) { |
mbedalvaro | 31:5f039cbddee8 | 199 | |
mbedalvaro | 31:5f039cbddee8 | 200 | Timer t; |
mbedalvaro | 31:5f039cbddee8 | 201 | t.start(); |
mbedalvaro | 31:5f039cbddee8 | 202 | while(t.read_ms()<times*1000) { |
mbedalvaro | 31:5f039cbddee8 | 203 | |
mbedalvaro | 31:5f039cbddee8 | 204 | writeOutX(MIN_AD_MIRRORS);writeOutY(MIN_AD_MIRRORS); |
mbedalvaro | 31:5f039cbddee8 | 205 | |
mbedalvaro | 31:5f039cbddee8 | 206 | for(int j=0; j<pointsPerLine; j++){ |
mbedalvaro | 31:5f039cbddee8 | 207 | wait_us(200);//delay between each points |
mbedalvaro | 31:5f039cbddee8 | 208 | writeOutY(j*shiftY + MIN_AD_MIRRORS); |
mbedalvaro | 31:5f039cbddee8 | 209 | } |
mbedalvaro | 31:5f039cbddee8 | 210 | |
mbedalvaro | 31:5f039cbddee8 | 211 | writeOutX(MIN_AD_MIRRORS);writeOutY(MAX_AD_MIRRORS); |
mbedalvaro | 31:5f039cbddee8 | 212 | for(int j=0; j<pointsPerLine; j++) { |
mbedalvaro | 31:5f039cbddee8 | 213 | wait_us(200);//delay between each points |
mbedalvaro | 31:5f039cbddee8 | 214 | writeOutX(j*shiftX + MIN_AD_MIRRORS); |
mbedalvaro | 31:5f039cbddee8 | 215 | } |
mbedalvaro | 31:5f039cbddee8 | 216 | |
mbedalvaro | 31:5f039cbddee8 | 217 | writeOutX(MAX_AD_MIRRORS);writeOutY(MAX_AD_MIRRORS); |
mbedalvaro | 31:5f039cbddee8 | 218 | for(int j=0; j<pointsPerLine; j++) { |
mbedalvaro | 31:5f039cbddee8 | 219 | wait_us(200);//delay between each points |
mbedalvaro | 31:5f039cbddee8 | 220 | writeOutY(-j*shiftX + MAX_AD_MIRRORS); |
mbedalvaro | 31:5f039cbddee8 | 221 | } |
mbedalvaro | 31:5f039cbddee8 | 222 | |
mbedalvaro | 31:5f039cbddee8 | 223 | writeOutX(MAX_AD_MIRRORS);writeOutY(MIN_AD_MIRRORS); |
mbedalvaro | 31:5f039cbddee8 | 224 | for(int j=0; j<pointsPerLine; j++) { |
mbedalvaro | 31:5f039cbddee8 | 225 | wait_us(200);//delay between each points |
mbedalvaro | 31:5f039cbddee8 | 226 | writeOutX(-j*shiftX + MAX_AD_MIRRORS); |
mbedalvaro | 31:5f039cbddee8 | 227 | } |
mbedalvaro | 31:5f039cbddee8 | 228 | |
mbedalvaro | 31:5f039cbddee8 | 229 | } |
mbedalvaro | 31:5f039cbddee8 | 230 | t.stop(); |
mbedalvaro | 31:5f039cbddee8 | 231 | Laser_Green=0; |
mbedalvaro | 31:5f039cbddee8 | 232 | } |
mbedalvaro | 31:5f039cbddee8 | 233 | |
mbedalvaro | 31:5f039cbddee8 | 234 | void HardwareIO::scan_serial(unsigned short pointsPerLine){ |
mbedalvaro | 31:5f039cbddee8 | 235 | //scan the total surface with a custom resolution |
mbedalvaro | 31:5f039cbddee8 | 236 | //send the lockin value for each point as a byte on the serial port to the PC |
mbedalvaro | 31:5f039cbddee8 | 237 | //use "scanSLP_save" to see the data on processing |
mbedalvaro | 31:5f039cbddee8 | 238 | |
mbedalvaro | 31:5f039cbddee8 | 239 | |
mbedalvaro | 31:5f039cbddee8 | 240 | int shiftX = (MAX_AD_MIRRORS - MIN_AD_MIRRORS) / pointsPerLine; |
mbedalvaro | 31:5f039cbddee8 | 241 | int shiftY = (MAX_AD_MIRRORS - MIN_AD_MIRRORS) / pointsPerLine; |
mbedalvaro | 31:5f039cbddee8 | 242 | |
mbedalvaro | 31:5f039cbddee8 | 243 | for(int j=0; j<pointsPerLine; j++){ |
mbedalvaro | 31:5f039cbddee8 | 244 | writeOutX(MIN_AD_MIRRORS); |
mbedalvaro | 31:5f039cbddee8 | 245 | writeOutY(j*shiftY + MIN_AD_MIRRORS); |
mbedalvaro | 31:5f039cbddee8 | 246 | |
mbedalvaro | 31:5f039cbddee8 | 247 | wait_us(300);//begining of line delay |
mbedalvaro | 31:5f039cbddee8 | 248 | for(int i=0; i<pointsPerLine; i++){ |
mbedalvaro | 31:5f039cbddee8 | 249 | writeOutX(i*shiftX + MIN_AD_MIRRORS); |
mbedalvaro | 31:5f039cbddee8 | 250 | |
mbedalvaro | 31:5f039cbddee8 | 251 | wait_us(200);//delay between each points |
mbedalvaro | 31:5f039cbddee8 | 252 | |
mbedalvaro | 31:5f039cbddee8 | 253 | // SEND A VALUE BETWEEN 0 and 255: |
mbedalvaro | 31:5f039cbddee8 | 254 | pc.putc(int(255.0*lockin.getMedianValue()/4095));//printf("%dL",int(valueLockin*255));//pc.putc(int(lockin*255));// |
mbedalvaro | 31:5f039cbddee8 | 255 | } |
mbedalvaro | 31:5f039cbddee8 | 256 | } |
mbedalvaro | 31:5f039cbddee8 | 257 | } |
mbedalvaro | 31:5f039cbddee8 | 258 | |
mbedalvaro | 31:5f039cbddee8 | 259 | //load Look-up Table from LUT.TXT file |
mbedalvaro | 31:5f039cbddee8 | 260 | //or create the file with scanLUT() if not existing. |
mbedalvaro | 31:5f039cbddee8 | 261 | void HardwareIO::setLUT(){ |
mbedalvaro | 31:5f039cbddee8 | 262 | |
mbedalvaro | 31:5f039cbddee8 | 263 | FILE *fp = fopen(LUT_FILENAME, "r"); // Open file on the local file system for writing |
mbedalvaro | 31:5f039cbddee8 | 264 | if(fp){ |
mbedalvaro | 31:5f039cbddee8 | 265 | //load the file into the lut table; keep the SAME resolution! |
mbedalvaro | 31:5f039cbddee8 | 266 | fread(lut,sizeof(uint16),LUT_RESOLUTION*LUT_RESOLUTION,fp); |
mbedalvaro | 31:5f039cbddee8 | 267 | fclose(fp); |
mbedalvaro | 31:5f039cbddee8 | 268 | } |
mbedalvaro | 31:5f039cbddee8 | 269 | else{ |
mbedalvaro | 31:5f039cbddee8 | 270 | //fclose(fp); |
mbedalvaro | 31:5f039cbddee8 | 271 | //if the file "LUT.TXT" doesn't exist, create one with scanLUT() |
mbedalvaro | 31:5f039cbddee8 | 272 | lockin.setLaserPower(true); |
mbedalvaro | 31:5f039cbddee8 | 273 | scanLUT(); |
mbedalvaro | 31:5f039cbddee8 | 274 | } |
mbedalvaro | 31:5f039cbddee8 | 275 | |
mbedalvaro | 31:5f039cbddee8 | 276 | } |
mbedalvaro | 31:5f039cbddee8 | 277 | |
mbedalvaro | 31:5f039cbddee8 | 278 | //scan the total surface with a fixed 2^x resolution |
mbedalvaro | 31:5f039cbddee8 | 279 | //create the Look-Up Table used to "flatten" the scan according to the position |
mbedalvaro | 31:5f039cbddee8 | 280 | // |
mbedalvaro | 31:5f039cbddee8 | 281 | //To Do: maybe detect high frequency to be sure the area is clean and empty? |
mbedalvaro | 31:5f039cbddee8 | 282 | void HardwareIO::scanLUT(){ |
mbedalvaro | 31:5f039cbddee8 | 283 | |
mbedalvaro | 31:5f039cbddee8 | 284 | //reset lut table |
mbedalvaro | 31:5f039cbddee8 | 285 | for(int j=0; j<LUT_RESOLUTION; j++){ |
mbedalvaro | 31:5f039cbddee8 | 286 | for(int i=0; i<LUT_RESOLUTION; i++){ |
mbedalvaro | 31:5f039cbddee8 | 287 | lut[i][j] =0; |
mbedalvaro | 31:5f039cbddee8 | 288 | } |
mbedalvaro | 31:5f039cbddee8 | 289 | } |
mbedalvaro | 31:5f039cbddee8 | 290 | |
mbedalvaro | 31:5f039cbddee8 | 291 | int delayScanning = 300; //in us |
mbedalvaro | 31:5f039cbddee8 | 292 | |
mbedalvaro | 31:5f039cbddee8 | 293 | //define the distance between each points (from 0 to 4096) and the offset (here 0) |
mbedalvaro | 31:5f039cbddee8 | 294 | float shiftX = 1.0*(MAX_AD_MIRRORS - MIN_AD_MIRRORS) / (LUT_RESOLUTION-1); |
mbedalvaro | 31:5f039cbddee8 | 295 | float shiftY = 1.0*(MAX_AD_MIRRORS - MIN_AD_MIRRORS) / (LUT_RESOLUTION-1); |
mbedalvaro | 31:5f039cbddee8 | 296 | float offsetX = MIN_AD_MIRRORS; |
mbedalvaro | 31:5f039cbddee8 | 297 | float offsetY = MIN_AD_MIRRORS; |
mbedalvaro | 31:5f039cbddee8 | 298 | |
mbedalvaro | 31:5f039cbddee8 | 299 | //move the mirrors to the first position |
mbedalvaro | 31:5f039cbddee8 | 300 | writeOutX(MAX_AD_MIRRORS);writeOutY(MIN_AD_MIRRORS); |
mbedalvaro | 31:5f039cbddee8 | 301 | wait_us(500); |
mbedalvaro | 31:5f039cbddee8 | 302 | |
mbedalvaro | 31:5f039cbddee8 | 303 | float x, y; |
mbedalvaro | 31:5f039cbddee8 | 304 | |
mbedalvaro | 31:5f039cbddee8 | 305 | //scan the surface NB_SCANS times |
mbedalvaro | 31:5f039cbddee8 | 306 | //the total value in lut[i][j] shouldn't exceed uint16 !!! |
mbedalvaro | 31:5f039cbddee8 | 307 | for(int loop=0; loop<NB_SCANS; loop++){ |
mbedalvaro | 31:5f039cbddee8 | 308 | for(int j=0; j<LUT_RESOLUTION; j++){ |
mbedalvaro | 31:5f039cbddee8 | 309 | y = shiftY*j + offsetY ; |
mbedalvaro | 31:5f039cbddee8 | 310 | writeOutY(int(y)); |
mbedalvaro | 31:5f039cbddee8 | 311 | //scan from right to left |
mbedalvaro | 31:5f039cbddee8 | 312 | for(int i=LUT_RESOLUTION-1; i>=0; i--){ |
mbedalvaro | 31:5f039cbddee8 | 313 | x = shiftX*i + offsetX; |
mbedalvaro | 31:5f039cbddee8 | 314 | writeOutX(int(x)); |
mbedalvaro | 31:5f039cbddee8 | 315 | wait_us(delayScanning); |
mbedalvaro | 31:5f039cbddee8 | 316 | lut[i][j] += lockin_read(); |
mbedalvaro | 31:5f039cbddee8 | 317 | } |
mbedalvaro | 31:5f039cbddee8 | 318 | //re-scan from left to right |
mbedalvaro | 31:5f039cbddee8 | 319 | for(int i=0; i<LUT_RESOLUTION; i++){ |
mbedalvaro | 31:5f039cbddee8 | 320 | x = shiftX*i + offsetX; |
mbedalvaro | 31:5f039cbddee8 | 321 | writeOutX(int(x)); |
mbedalvaro | 31:5f039cbddee8 | 322 | wait_us(delayScanning); |
mbedalvaro | 31:5f039cbddee8 | 323 | lut[i][j] += lockin_read(); |
mbedalvaro | 31:5f039cbddee8 | 324 | } |
mbedalvaro | 31:5f039cbddee8 | 325 | } |
mbedalvaro | 31:5f039cbddee8 | 326 | } |
mbedalvaro | 31:5f039cbddee8 | 327 | |
mbedalvaro | 31:5f039cbddee8 | 328 | |
mbedalvaro | 31:5f039cbddee8 | 329 | //save tab in file |
mbedalvaro | 31:5f039cbddee8 | 330 | FILE *fp; |
mbedalvaro | 31:5f039cbddee8 | 331 | #ifdef LUT_FILENAME |
mbedalvaro | 31:5f039cbddee8 | 332 | fp = fopen(LUT_FILENAME, "w"); // Open file on the local file system for writing |
mbedalvaro | 31:5f039cbddee8 | 333 | fwrite(lut,sizeof(uint16),LUT_RESOLUTION*LUT_RESOLUTION,fp); |
mbedalvaro | 31:5f039cbddee8 | 334 | fclose(fp); //close the file (the mBed will appear connected again) |
mbedalvaro | 31:5f039cbddee8 | 335 | #endif |
mbedalvaro | 31:5f039cbddee8 | 336 | |
mbedalvaro | 31:5f039cbddee8 | 337 | #ifdef LUT_H_FILENAME |
mbedalvaro | 31:5f039cbddee8 | 338 | //save tab in Human readable file (not used by the program, this is just for checking) |
mbedalvaro | 31:5f039cbddee8 | 339 | // NOTE: we divide the content of the lut table by NB_SCANS, for easy reading (values should be between 0-4095) |
mbedalvaro | 31:5f039cbddee8 | 340 | fp = fopen(LUT_H_FILENAME, "w"); // Open file on the local file system for writing |
mbedalvaro | 31:5f039cbddee8 | 341 | fprintf(fp, "scan resolution: %d x %d\r\n",LUT_RESOLUTION, LUT_RESOLUTION); |
mbedalvaro | 31:5f039cbddee8 | 342 | for(int j=0; j<LUT_RESOLUTION; j++){ |
mbedalvaro | 31:5f039cbddee8 | 343 | for(int i=0; i<LUT_RESOLUTION; i++){ |
mbedalvaro | 31:5f039cbddee8 | 344 | fprintf(fp, "X=%d,\tY=%d,\tI=%d\t \r\n", int(shiftX*i + offsetX), int(shiftY*j + offsetY), int(1.0*lut[i][j]/NB_SCANS) ); |
mbedalvaro | 31:5f039cbddee8 | 345 | } |
mbedalvaro | 31:5f039cbddee8 | 346 | } |
mbedalvaro | 31:5f039cbddee8 | 347 | fclose(fp); //close the file (the mBed will appear connected again) |
mbedalvaro | 31:5f039cbddee8 | 348 | #endif |
mbedalvaro | 31:5f039cbddee8 | 349 | |
mbedalvaro | 31:5f039cbddee8 | 350 | } |
mbedalvaro | 31:5f039cbddee8 | 351 | |
mbedalvaro | 31:5f039cbddee8 | 352 | |
mbedalvaro | 31:5f039cbddee8 | 353 | //Return the lockin value "corrected with the Look-UpTable" - this means a RATIO between two reflectivities (and normally, this is <1). |
mbedalvaro | 31:5f039cbddee8 | 354 | float HardwareIO::lockInCorrectedValue(unsigned short x, unsigned short y){ |
mbedalvaro | 31:5f039cbddee8 | 355 | //*******Correction using DIRECT approximation |
mbedalvaro | 31:5f039cbddee8 | 356 | #ifdef LUT_DIRECT |
mbedalvaro | 31:5f039cbddee8 | 357 | return 2.0* NB_SCANS * lockin_read() / (lut[x >> LUT_BITS_SHIFT][y >> LUT_BITS_SHIFT]); // 2 * NB_SCANS is the number of recorded sample added to one position of the LUT (scan is performed twice: left-right and right-left) |
mbedalvaro | 31:5f039cbddee8 | 358 | #endif |
mbedalvaro | 31:5f039cbddee8 | 359 | |
mbedalvaro | 31:5f039cbddee8 | 360 | //*******Correction using BILINEAR approximation |
mbedalvaro | 31:5f039cbddee8 | 361 | #ifdef LUT_BILINEAR |
mbedalvaro | 31:5f039cbddee8 | 362 | unsigned short X = x >> LUT_BITS_SHIFT; //mirror "x" is 12bits, LUT "X" needs 4bits when lut is 17x17 |
mbedalvaro | 31:5f039cbddee8 | 363 | unsigned short Y = y >> LUT_BITS_SHIFT; //mirror "y" is 12bits, LUT "Y" needs 4bits when lut is 17x17 |
mbedalvaro | 31:5f039cbddee8 | 364 | float dx = 1.0*(x & LUT_BITS_MASK)/(LUT_BITS_MASK+1); //weight to apply on X (mask with 255 and norm) |
mbedalvaro | 31:5f039cbddee8 | 365 | float dy = 1.0*(y & LUT_BITS_MASK)/(LUT_BITS_MASK+1); //weight to apply on Y (mask with 255 and norm) |
mbedalvaro | 31:5f039cbddee8 | 366 | |
mbedalvaro | 31:5f039cbddee8 | 367 | //Wheighted mean approximation of the Look-Up Table at the position (x,y): |
mbedalvaro | 31:5f039cbddee8 | 368 | float wmLUT = (1-dy)*( (1-dx)*lut[X][Y] + dx*lut[X+1][Y] ) + dy*( (1-dx)*lut[X][Y+1] + dx*lut[X+1][Y+1] ); |
mbedalvaro | 31:5f039cbddee8 | 369 | |
mbedalvaro | 31:5f039cbddee8 | 370 | return 2.0* NB_SCANS * lockin_read() / wmLUT;// 2 * NB_SCANS is the number of recorded sample added to one position of the LUT (scan is performed twice: left-right and right-left) |
mbedalvaro | 31:5f039cbddee8 | 371 | #endif |
mbedalvaro | 31:5f039cbddee8 | 372 | |
mbedalvaro | 31:5f039cbddee8 | 373 | //*******Correction using LINEAR approximation |
mbedalvaro | 31:5f039cbddee8 | 374 | #ifdef LUT_LINEAR |
mbedalvaro | 31:5f039cbddee8 | 375 | unsigned short X = x >> LUT_BITS_SHIFT; //mirror "x" is 12bits, LUT "X" needs 4bits when lut is 17x17 |
mbedalvaro | 31:5f039cbddee8 | 376 | unsigned short Y = y >> LUT_BITS_SHIFT; //mirror "y" is 12bits, LUT "Y" needs 4bits when lut is 17x17 |
mbedalvaro | 31:5f039cbddee8 | 377 | float dx = 1.0*(x & LUT_BITS_MASK)/(LUT_BITS_MASK+1); //weight to apply on X (mask with 255 and norm) |
mbedalvaro | 31:5f039cbddee8 | 378 | float dy = 1.0*(y & LUT_BITS_MASK)/(LUT_BITS_MASK+1); //weight to apply on Y (mask with 255 and norm) |
mbedalvaro | 31:5f039cbddee8 | 379 | float linearLUT, dzx, dzy; |
mbedalvaro | 31:5f039cbddee8 | 380 | |
mbedalvaro | 31:5f039cbddee8 | 381 | if(dx>dy){ //if the position is on the "top-right" triangle |
mbedalvaro | 31:5f039cbddee8 | 382 | dzx = (lut[X+1][Y] - lut[X][Y]) * dx; |
mbedalvaro | 31:5f039cbddee8 | 383 | dzy = (lut[X+1][Y+1] - lut[X+1][Y]) * dy; |
mbedalvaro | 31:5f039cbddee8 | 384 | } |
mbedalvaro | 31:5f039cbddee8 | 385 | else{ //if the position is on the "bottom-left" triangle |
mbedalvaro | 31:5f039cbddee8 | 386 | dzy = (lut[X][Y+1] - lut[X][Y]) * dy; |
mbedalvaro | 31:5f039cbddee8 | 387 | dzx = (lut[X+1][Y+1] - lut[X][Y+1]) * dx; |
mbedalvaro | 31:5f039cbddee8 | 388 | } |
mbedalvaro | 31:5f039cbddee8 | 389 | |
mbedalvaro | 31:5f039cbddee8 | 390 | //linear approximation of the Look-Up Table at the position (x,y): |
mbedalvaro | 31:5f039cbddee8 | 391 | linearLUT = lut[X][Y] + dzx + dzy; |
mbedalvaro | 31:5f039cbddee8 | 392 | return 2.0* NB_SCANS * lockin_read() / linearLUT; // 2 * NB_SCANS is the number of recorded sample added to one position of the LUT (scan is performed twice: left-right and right-left) |
mbedalvaro | 31:5f039cbddee8 | 393 | |
mbedalvaro | 31:5f039cbddee8 | 394 | #endif |
mbedalvaro | 31:5f039cbddee8 | 395 | |
mbedalvaro | 31:5f039cbddee8 | 396 | //*******No corrections, just return the value divided by 4096 (this means we are assuming that the surface is everywhere perfectly reflective - we supposedly get the max value always) |
mbedalvaro | 31:5f039cbddee8 | 397 | #ifdef NO_LUT |
mbedalvaro | 31:5f039cbddee8 | 398 | return 1.0* lockin_read()/4096; |
mbedalvaro | 31:5f039cbddee8 | 399 | #endif |
mbedalvaro | 31:5f039cbddee8 | 400 | |
mbedalvaro | 31:5f039cbddee8 | 401 | } |