/* --------------------------------------------------------------------------- * calibrateaio.c (c) 2008 Micro-key bv * --------------------------------------------------------------------------- * Micro-key bv * Industrieweg 28, 9804 TG Noordhorn * Postbus 92, 9800 AB Zuidhorn * The Netherlands * Tel: +31 594 503020 * Fax: +31 594 505825 * Email: support@microkey.nl * Web: www.microkey.nl * --------------------------------------------------------------------------- * Description: * --------------------------------------------------------------------------- * Version(s): 0.1, Mei 22, 2008, MMi * Creation. * --------------------------------------------------------------------------- */ /* APPLICATION NOTES: * Voltage Input Calibration: All Inputs need to be connected to the defined, * preset Voltage Value (e.g. 10 V). * * Voltage Output Calibration: Output 0-3 need to be connected to own Inputs * 0-3. * * Current Input Calibration: All Inputs need to be connected to the defined, * preset Current Value (e.g. 20 mA per channel) * * Current Output Calibration: Output 0-3 need to be connected to own Inputs * 0-3. All other Connections must be removed. */ /* --------------------------------------------------------------------------- * System include files * --------------------------------------------------------------------------- */ #include #include "lpc23xx.h" #include "types.h" /* FreeRTOS includes */ #include "FreeRTOS.h" #include "Task.h" #include "semphr.h" /* --------------------------------------------------------------------------- * Application include files * --------------------------------------------------------------------------- */ #include "calibrateaio.h" #include "adc.h" #include "dac.h" #include "dio.h" #include "eeprom.h" #include "ssp0.h" #include "BusProtocol.h" #include "serial.h" #include "SerOut.h" /* --------------------------------------------------------------------------- * Local constant and macro definitions * --------------------------------------------------------------------------- */ #define NumberOfOutputChannels maxDAC_Channels /* See dac.h */ #define NumberOfInputChannels maxADC_Channels /* See adc.h */ #define MaximumCurrent 20000 /* Maximum driveable Current */ #define MaximumVoltage 10000 /* Maximum driveable Voltage */ /* Addresses, where correction factors are stored in the EEPROM */ #define VI_Address 0x00 /* Adress of Voltage Input Factor */ #define CI_Address 0x10 /* Adress of Current Input Factor */ #define VO_Address 0x20 /* Adress of Voltage Output Factor */ // \MARK NEW PINSETTINGS FOR TESTER (2) #if (PINSET_TESTER == 2) #define CO_Address 0x30 /* Adress of Current Output Factor */ #else #define CO_Address 0x28 /* Adress of Current Output Factor */ #endif #define VI_ByteLength 0x10 /* Length of VI Entry in Bytes */ #define CI_ByteLength 0x10 /* Length of CI Entry in Bytes */ // \MARK NEW PINSETTINGS FOR TESTER (2) #if (PINSET_TESTER == 2) #define VO_ByteLength 0x10 /* Length of VO Entry in Bytes */ #define CO_ByteLength 0x10 /* Length of CO Entry in Bytes */ #else #define VO_ByteLength 0x08 /* Length of VO Entry in Bytes */ #define CO_ByteLength 0x08 /* Length of CO Entry in Bytes */ #endif // \MARK NEW PINSETTINGS FOR TESTER (2) #if (PINSET_TESTER == 2) #define ident_VoltageInput 0x40 /* Stat of Volt. Input Calibration */ #define ident_VoltageOutput 0x41 /* Stat of Volt. Output Calibration */ #define ident_CurrentInput 0x42 /* Stat of Curr. Input Calibration */ #define ident_CurrentOutput 0x43 /* Stat of Curr. Output Calibration */ #else #define ident_VoltageInput 0x30 /* Stat of Volt. Input Calibration */ #define ident_VoltageOutput 0x31 /* Stat of Volt. Output Calibration */ #define ident_CurrentInput 0x32 /* Stat of Curr. Input Calibration */ #define ident_CurrentOutput 0x33 /* Stat of Curr. Output Calibration */ #endif #define DAC_CHANNEL_A (0x8000) #define DAC_CHANNEL_B (0x0000) #define spiWriteBuffer ssp0WriteBuffer #define spiReadBuffer ssp0ReadBuffer /* --------------------------------------------------------------------------- * Global variable definitions * --------------------------------------------------------------------------- */ /* External Arrays where system stores calibration values for temporary use */ extern UINT16 OutputVoltageCorrection[NumberOfOutputChannels]; extern UINT16 OutputCurrentCorrection[NumberOfOutputChannels]; extern UINT16 InputVoltageCorrection[NumberOfInputChannels]; extern UINT16 InputCurrentCorrection[NumberOfInputChannels]; /* --------------------------------------------------------------------------- * Local variable definitions * --------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------- * Local function definitions * --------------------------------------------------------------------------- */ void killStats (void) { eepromWrite(ident_VoltageInput, 0x00); /* Write 0x00 to EEPROM Adress */ eepromWrite(ident_VoltageOutput, 0x00); eepromWrite(ident_CurrentInput, 0x00); eepromWrite(ident_CurrentOutput, 0x00); } void defaultStats (void) { eepromWrite(ident_VoltageInput, ident_default); /* Write DEFAULT Value */ eepromWrite(ident_VoltageOutput, ident_default); eepromWrite(ident_CurrentInput, ident_default); eepromWrite(ident_CurrentOutput, ident_default); } void calibratedStats (void) { eepromWrite(ident_VoltageInput, ident_calibrated); /* Write CALIBRATED */ eepromWrite(ident_VoltageOutput, ident_calibrated); eepromWrite(ident_CurrentInput, ident_calibrated); eepromWrite(ident_CurrentOutput, ident_calibrated); } void calibrationInit (void) { UINT8 volin; UINT8 volout; UINT8 curin; UINT8 curout; /* Readout Stats from EEPROM */ eepromRead(ident_VoltageInput, &volin); eepromRead(ident_VoltageOutput, &volout); eepromRead(ident_CurrentInput, &curin); eepromRead(ident_CurrentOutput, &curout); /* If a Stat is not defined, delete the Values and reset them to DEFAULT*/ if ((volin != ident_default) && (volin != ident_calibrated)) { deleteCorrectionValue(VoltageInput); loadCorrectionValue_defaultTarget(VoltageInput); } if ((volout != ident_default) && (volout != ident_calibrated)) { deleteCorrectionValue(VoltageOutput); loadCorrectionValue_defaultTarget(VoltageOutput); } if ((curin != ident_default) && (curin != ident_calibrated)) { deleteCorrectionValue(CurrentInput); loadCorrectionValue_defaultTarget(CurrentInput); } if ((curout != ident_default) && (curout != ident_calibrated)) { deleteCorrectionValue(CurrentOutput); loadCorrectionValue_defaultTarget(CurrentOutput); } } UINT8 returnCalibrationStatus (daadCorrection_t correctionType) { UINT8 readback; /* read corresponding Stats from EEPROM */ switch (correctionType) { case VoltageInput: eepromRead(ident_VoltageInput, &readback); break; case VoltageOutput: eepromRead(ident_VoltageOutput, &readback); break; case CurrentInput: eepromRead(ident_CurrentInput, &readback); break; case CurrentOutput: eepromRead(ident_CurrentOutput, &readback); break; } return (readback); /* Return read Value to Caller */ } UINT8 showLocalCalibrationStatus (INT32 correctionType) { UINT8 readback; readback = returnCalibrationStatus (correctionType); if (readback & ident_default) { sendString (SerOutPort, FALSE, importantMessage, "Values are in DEFAULT Mode", Dummy, Dummy); } else if (readback & ident_calibrated) { sendString (SerOutPort, FALSE, importantMessage, "Values are in CALIBRATED Mode", Dummy, Dummy); } else { sendString (SerOutPort, FALSE, importantMessage, "NO VALID VALUES IN EEPROM", Dummy, Dummy); } return (readback); } /* Calibration of Analogue Inputs in Voltage Mode: * Attach Voltage Supply with Calibration Value (recommended: 10,000 V) to * the Input(s) you want to calibrate. Software will read out the real, * digital Value from the ADC and uses this as Point of Calibration. Value * will be stored in EEPROM (Adresses see above). */ void calibrateVoltageInput(void) { /* Local Variable Declaration */ UINT32 adcResult; UINT32 loopcnt; UINT16 VoltageInputCorrection[8]; UINT8 spiAdcCommand[3]; UINT8 spiAdcResponse[3]; /* Delete/Reset old Calibration Values */ deleteCorrectionValue (VoltageInput); /* Load default Calibration Values from EEPROM */ loadCorrectionValue(InputVoltageCorrection, VoltageInput); adcModeAll (adcVOLTAGE); /* Set ADC to Mode VOLTAGE */ loopcnt = 0; do /* Do single for every Input */ { /* Reset readback Variables */ adcResult = 0; spiAdcResponse[0] = 0; spiAdcResponse[1] = 0; spiAdcResponse[2] = 0; /* Build SPI Command */ spiAdcCommand[0] = 0x06; spiAdcCommand[0] |= (loopcnt >> 2) & 0x01; spiAdcCommand[1] = (loopcnt << 6); spiAdcCommand[2] = 0; FIO1CLR = BIT( 25 ); /* Enable Chipselect of ADC */ spiWriteBuffer( spiAdcCommand, 3 ); /* send Command */ spiReadBuffer( spiAdcResponse, 3 ); /* receive Response */ FIO1SET = BIT( 25 ); /* Disbale Chipselect of ADC */ /* Build 12 Bit Result out of 8 and 4 Bit readBack */ adcResult = (UINT16)(spiAdcResponse[1] & 0x0F) << 8; adcResult |= (UINT16)spiAdcResponse[2]; /* Store result in Array for Voltage Input Correction */ VoltageInputCorrection[loopcnt] = adcResult; loopcnt++; } while (loopcnt < NumberOfInputChannels); /* Save Correction Values to EEPROM */ saveCorrectionValue(VoltageInputCorrection, VoltageInput); /* Load new Calibration Values from EEPROM */ loadCorrectionValue(InputVoltageCorrection, VoltageInput); } /* Calibration of Analogue Outputs in Voltage Mode: * Attach the Output you want to calibrate to its corresponding Input * (e.g. Output 1 to Input 1). Software will set up In- and Outputs * automatically. The Correction Value will be calculated and stored in * the EEPROM (Adresses see above). */ void calibrateVoltageOutput (void) { UINT16 spiCommand; UINT16 channel = 0; UINT16 value = 0xF80; UINT16 readVoltage; UINT16 VoltageOutputCorrection[4]; BOOLEAN leaveloop = FALSE; /* Delete/Reset old Calibration Values */ deleteCorrectionValue (VoltageOutput); /* Load default Calibration Values from EEPROM */ loadCorrectionValue(OutputVoltageCorrection, VoltageOutput); dacModeAll (dacVOLTAGE); /* Set Output Types to Voltage */ adcModeAll (dacVOLTAGE); /* Set Input Types to Voltage */ vTaskDelay (100); do /* Single for every Channel */ { do /* As long as false channel Result */ { /* Build and send SPI Command */ spiCommand = 0x3000; spiCommand |= ((channel & 0x01) == 0x01 ? DAC_CHANNEL_B : DAC_CHANNEL_A); spiCommand |= (UINT16) value; WriteDacCommand( spiCommand, (channel >> 1)); vTaskDelay (50); readVoltage = adcRead (0, channel); /* Is Result exactly 10000? * If so, wait for 1 Second and test again. If no change, Result * is OK and Correction Value is stored. If not, test further */ if (readVoltage == 10000) { vTaskDelay (1000); if ((readVoltage = adcRead (0, channel)) == 10000) { VoltageOutputCorrection[channel] = value; leaveloop = TRUE; } } /* If Readback is too: * LOW: increase Output and try again * HIGH: decrease Output and try again */ else if (readVoltage > 10000) { value -= 0x01; } else if (readVoltage < 10000) { value += 0x01; } } while (leaveloop == FALSE); /* Reset loop Values for next Channel */ leaveloop = FALSE; value = 0xF80; channel++; } while (channel < NumberOfOutputChannels); /* Save Correction Values to EEPROM */ saveCorrectionValue(VoltageOutputCorrection, VoltageOutput); /* Load new Calibration Values from EEPROM */ loadCorrectionValue(OutputVoltageCorrection, VoltageOutput); } /* Calibration of Analogue Inputs in Current Mode: * Attach Current Supply with Calibration Value (recommended: 20,000 mA) to * the first Input you want to calibrate. Software will read out the real, * digital Value from the ADC and uses this as Point of Calibration. Continue * with the next channel when software prompts to press enter. * Value will be stored in EEPROM (Adresses see above). * NEVER CONNECT MORE THAN ONE CHANNEL TO CURRENT SUPPLY ONCE */ void calibrateCurrentInput (void) { UINT32 channel = 0; UINT16 adcResult; UINT16 CurrentInputCorrection[8]; UINT8 buffer; UINT8 spiAdcCommand[3]; UINT8 spiAdcResponse[3]; BOOLEAN receive; /* Delete/Reset old Calibration Values */ deleteCorrectionValue (CurrentInput); /* Load default Calibration Values from EEPROM */ loadCorrectionValue(InputCurrentCorrection, CurrentInput); adcModeAll (adcCURRENT); /* Set ADC Mode to CURRENT */ vTaskDelay (100); do /* Single for every Channel */ { /* Just for Testing!!! */ receive = FALSE; buffer = 0; sendString (SerOutPort, TRUE, importantMessage, "Press ENTER to continue with Channel ", ItoDStr (channel), Dummy); do /* do-while loop for String input */ { vTaskDelay (10); receive = serGet(MenuPort, &buffer); } while ((buffer != 13) && (buffer != 32)); /* Reset readback Variables */ adcResult = 0x00; spiAdcResponse[0] = 0; spiAdcResponse[1] = 0; spiAdcResponse[2] = 0; /* Build SPI Command */ spiAdcCommand[0] = 0x06; spiAdcCommand[0] |= (channel >> 2) & 0x01; spiAdcCommand[1] = (channel << 6); spiAdcCommand[2] = 0; FIO1CLR = BIT( 25 ); /* ADC chipselect enable */ spiWriteBuffer( spiAdcCommand, 3 ); /* Send SPI Command */ spiReadBuffer( spiAdcResponse, 3 ); /* Receive Response */ FIO1SET = BIT( 25 ); /* ADC Chipselect disable */ /* Build 12 Bit Result out of 8 and 4 Bit readBack */ adcResult = (UINT16)(spiAdcResponse[1] & 0x0F) << 8; adcResult |= (UINT16)spiAdcResponse[2]; /* Store Value to Array */ CurrentInputCorrection[channel] = adcResult; channel++; /* Test next Channel */ } while (channel < 8); /* Save Correction Values to EEPROM */ saveCorrectionValue(CurrentInputCorrection, CurrentInput); /* Load new Calibration Values from EEPROM */ loadCorrectionValue(InputCurrentCorrection, CurrentInput); } /* Connect Analogue Outputs to the corresponding analogue Inputs. Software * will prevent of double-usage of channels. * Values will be stored in EEPROM automatically */ void calibrateCurrentOutput (void) { UINT16 spiCommand; UINT16 channel = 0; UINT16 value = 0xF80; UINT16 readCurrent; UINT16 CurrentOutputCorrection[4]; BOOLEAN leaveloop = FALSE; /* Delete/Reset old Calibration Values */ deleteCorrectionValue (CurrentOutput); /* Load default Calibration Values from EEPROM */ loadCorrectionValue(OutputCurrentCorrection, CurrentOutput); dacModeAll (dacCURRENT); /* Set Output Types to Voltage */ adcMode(0, adcCURRENT); adcMode(1, adcCURRENT); adcMode(2, adcCURRENT); adcMode(3, adcCURRENT); adcMode(4, adcVOLTAGE); adcMode(5, adcVOLTAGE); adcMode(6, adcVOLTAGE); adcMode(7, adcVOLTAGE); vTaskDelay (100); do /* Single for every Channel */ { do /* As long as false channel Result */ { /* Build and send SPI Command */ spiCommand = 0x3000; spiCommand |= ((channel & 0x01) == 0x01 ? DAC_CHANNEL_B : DAC_CHANNEL_A); spiCommand |= (UINT16) value; WriteDacCommand( spiCommand, (channel >> 1)); vTaskDelay (50); readCurrent = adcRead (0, channel); /* Is Result exactly 20000? * If so, wait for 1 Second and test again. If no change, Result * is OK and Correction Value is stored. If not, test further */ if (readCurrent == 20000) { vTaskDelay (1000); if ((readCurrent = adcRead (0, channel)) == 20000) { CurrentOutputCorrection[channel] = value; leaveloop = TRUE; } } /* If Readback is too: * LOW: increase Output and try again * HIGH: decrease Output and try again */ else if (readCurrent > 20000) { value -= 0x01; } else if (readCurrent < 20000) { value += 0x01; } } while (leaveloop == FALSE); /* Reset loop Values for next Channel */ leaveloop = FALSE; value = 0xF80; channel++; } while (channel < NumberOfOutputChannels); /* Save Correction Values to EEPROM */ saveCorrectionValue(CurrentOutputCorrection, CurrentOutput); /* Load new Calibration Values from EEPROM */ loadCorrectionValue(OutputCurrentCorrection, CurrentOutput); } void saveCorrectionValue(pUINT16 CorrectionValueArray, daadCorrection_t correctionType) { UINT32 loopcnt = 0; UINT8 sendBuffer[16]; switch (correctionType) { case VoltageInput: /* Voltage Input Correction */ while (loopcnt < NumberOfInputChannels) { /* Build 8Bit Array out of 16Bit Array */ sendBuffer [2*loopcnt] = (CorrectionValueArray[loopcnt] & 0x00FF); sendBuffer [2*loopcnt+1] = ((CorrectionValueArray[loopcnt] & 0xFF00) >> 8); loopcnt++; } /* Send built Array to EEPROM with specific Address and Length */ eepromWriteBuffer(VI_Address, sendBuffer, VI_ByteLength); eepromWrite(ident_VoltageInput, ident_calibrated); break; case VoltageOutput: /* Voltage Output Correction */ while (loopcnt < NumberOfOutputChannels) { sendBuffer [2*loopcnt] = (CorrectionValueArray[loopcnt] & 0x00FF); sendBuffer [2*loopcnt+1] = ((CorrectionValueArray[loopcnt] & 0xFF00) >> 8); loopcnt++; } eepromWriteBuffer(VO_Address, sendBuffer, VO_ByteLength); eepromWrite(ident_VoltageOutput, ident_calibrated); break; case CurrentInput: /* Current Input Correction */ while (loopcnt < NumberOfInputChannels) { sendBuffer [2*loopcnt] = (CorrectionValueArray[loopcnt] & 0x00FF); sendBuffer [2*loopcnt+1] = ((CorrectionValueArray[loopcnt] & 0xFF00) >> 8); loopcnt++; } eepromWriteBuffer(CI_Address, sendBuffer, CI_ByteLength); eepromWrite(ident_CurrentInput, ident_calibrated); break; case CurrentOutput: /* Current Output Correction */ while (loopcnt < NumberOfOutputChannels) { sendBuffer [2*loopcnt] = (CorrectionValueArray[loopcnt] & 0x00FF); sendBuffer [2*loopcnt+1] = ((CorrectionValueArray[loopcnt] & 0xFF00) >> 8); loopcnt++; } eepromWriteBuffer(CO_Address, sendBuffer, CO_ByteLength); eepromWrite(ident_CurrentOutput, ident_calibrated); break; } } void loadCorrectionValue_defaultTarget (daadCorrection_t correctionType) { UINT32 loopcnt = 0; UINT8 receiveArray[16]; switch (correctionType) { case VoltageInput: /* Voltage Input Correction */ /* Read EEPROM entry on specific Address and Length */ eepromReadBuffer(VI_Address, receiveArray, VI_ByteLength); /* Build 16 Bit Array out of 8 Bit Array */ while (loopcnt < NumberOfInputChannels) { InputVoltageCorrection[loopcnt] = (receiveArray[2*loopcnt]&0xFF) | ((receiveArray[2*loopcnt+1]&0xFF) << 8); loopcnt++; } break; case VoltageOutput: /* Voltage Output Correction */ eepromReadBuffer(VO_Address, receiveArray, VO_ByteLength); while (loopcnt < NumberOfOutputChannels) { OutputVoltageCorrection[loopcnt] = (receiveArray[2*loopcnt]&0xFF) | ((receiveArray[2*loopcnt+1]&0xFF) << 8); loopcnt++; } break; case CurrentInput: /* Current Input Correction */ eepromReadBuffer(CI_Address, receiveArray, CI_ByteLength); while (loopcnt < NumberOfInputChannels) { InputCurrentCorrection[loopcnt] = (receiveArray[2*loopcnt]&0xFF) | ((receiveArray[2*loopcnt+1]&0xFF) << 8); loopcnt++; } break; case CurrentOutput: /* Current Output Correction */ eepromReadBuffer(CO_Address, receiveArray, CO_ByteLength); while (loopcnt < NumberOfOutputChannels) { OutputCurrentCorrection[loopcnt] = (receiveArray[2*loopcnt]&0xFF) | ((receiveArray[2*loopcnt+1]&0xFF) << 8); loopcnt++; } break; } } void loadCorrectionValue(pUINT16 CorrectionValueArray, daadCorrection_t correctionType) { UINT32 loopcnt = 0; UINT8 receiveArray[16]; switch (correctionType) { case VoltageInput: /* Voltage Input Correction */ /* Read EEPROM entry on specific Address and Length */ eepromReadBuffer(VI_Address, receiveArray, VI_ByteLength); /* Build 16 Bit Array out of 8 Bit Array */ while (loopcnt < NumberOfInputChannels) { CorrectionValueArray[loopcnt] = (receiveArray[2*loopcnt]&0xFF) | ((receiveArray[2*loopcnt+1]&0xFF) << 8); loopcnt++; } break; case VoltageOutput: /* Voltage Output Correction */ eepromReadBuffer(VO_Address, receiveArray, VO_ByteLength); while (loopcnt < NumberOfOutputChannels) { CorrectionValueArray[loopcnt] = (receiveArray[2*loopcnt]&0xFF) | ((receiveArray[2*loopcnt+1]&0xFF) << 8); loopcnt++; } break; case CurrentInput: /* Current Input Correction */ eepromReadBuffer(CI_Address, receiveArray, CI_ByteLength); while (loopcnt < NumberOfInputChannels) { CorrectionValueArray[loopcnt] = (receiveArray[2*loopcnt]&0xFF) | ((receiveArray[2*loopcnt+1]&0xFF) << 8); loopcnt++; } break; case CurrentOutput: /* Current Output Correction */ eepromReadBuffer(CO_Address, receiveArray, CO_ByteLength); while (loopcnt < NumberOfOutputChannels) { CorrectionValueArray[loopcnt] = (receiveArray[2*loopcnt]&0xFF) | ((receiveArray[2*loopcnt+1]&0xFF) << 8); loopcnt++; } break; } } void deleteCorrectionValue (daadCorrection_t correctionType) { UINT32 loopcnt; UINT8 emptyBuffer[16]; /* Build NULL-Array */ for (loopcnt = 0; loopcnt < NumberOfInputChannels; loopcnt++) { emptyBuffer[2*loopcnt] = 0xFF; emptyBuffer[2*loopcnt+1] = 0x0F; } switch (correctionType) { case VoltageInput: eepromWriteBuffer (VI_Address, emptyBuffer, VI_ByteLength); eepromWrite(ident_VoltageInput, ident_default); break; case VoltageOutput: eepromWriteBuffer (VO_Address, emptyBuffer, VO_ByteLength); eepromWrite(ident_VoltageOutput, ident_default); break; case CurrentInput: eepromWriteBuffer (CI_Address, emptyBuffer, CI_ByteLength); eepromWrite(ident_CurrentInput, ident_default); break; case CurrentOutput: eepromWriteBuffer (CO_Address, emptyBuffer, CO_ByteLength); eepromWrite(ident_CurrentOutput, ident_default); break; } }