diff --git a/ADbasic_program_buffered.bas b/ADbasic_program_buffered.bas index d9717586026d07364428ab5404ed28dfbde41a3f..93bcf0659c7f057f1b50894a44ee8c8fe8308ad8 100644 --- a/ADbasic_program_buffered.bas +++ b/ADbasic_program_buffered.bas @@ -12,7 +12,6 @@ ' Info_Last_Save = QI-ADWIN QI-ADWIN\labuser '<Header End> #include adwinpro_all.inc -Import Math.LIC ' Array Size Settings ' TODO: check these values in labscript_devices files @@ -44,17 +43,18 @@ DIM DATA_3[MAX_EVENTS] AS LONG 'Analog ouput value DIM DATA_4[MAX_PID_EVENTS] AS LONG 'Times for changing PID channels DIM DATA_5[MAX_PID_EVENTS] AS LONG 'PID A_OUT channel DIM DATA_6[MAX_PID_EVENTS] AS LONG 'PID A_In channel -DIM DATA_25[MAX_PID_EVENTS] AS FLOAT 'PID P values -DIM DATA_26[MAX_PID_EVENTS] AS FLOAT 'PID I values -DIM DATA_27[MAX_PID_EVENTS] AS FLOAT 'PID D values -DIM DATA_28[MAX_PID_EVENTS] AS LONG 'PID min values -DIM DATA_29[MAX_PID_EVENTS] AS LONG 'PID max values +DIM DATA_24[PIDNO] AS FLOAT 'PID channel for init parameters +DIM DATA_25[PIDNO] AS FLOAT 'PID P values +DIM DATA_26[PIDNO] AS FLOAT 'PID I values +DIM DATA_27[PIDNO] AS FLOAT 'PID D values +DIM DATA_28[PIDNO] AS LONG 'PID min values +DIM DATA_29[PIDNO] AS LONG 'PID max values +DIM DATA_30[MAX_PID_EVENTS] AS LONG 'PID start values ' Declare arrays for AIN Channel Timings DIM DATA_7[AINNO] AS LONG 'Start times for channel recording DIM DATA_8[AINNO] AS LONG 'End times for channel recording DIM DATA_9[AINNO] AS LONG 'Gain modes for AIN channels -DIM DATA_19[AINNO] AS LONG 'Storage rate for AIN channels DIM DATA_199[A_IN_BUFFER+16] AS LONG 'Recorded Data - add padding at the end to ensure no overflow happens DIM ain_index[AINNO] AS LONG 'Index of the data acquisition for each channel, to have the values sorted @@ -103,7 +103,6 @@ DIM set_target[AOUTNO] AS LONG ' Set values to be written to AOUTs DIM set_output[AOUTNO] AS LONG ' Set values to be written to AOUTs DIM set_pid[AOUTNO] AS LONG ' PID selection for each AOUT DIM act_values[PIDNO] AS LONG ' Analog values measured from AINs -DIM ain_rate[AINNO] AS LONG ' How often should the AIN value be stored for each channel, combined with DATA_7 and DATA_8 '========================================================================= @@ -178,6 +177,17 @@ init: 'Output set voltages P2_Start_DAC(AOUT1) P2_Start_DAC(AOUT2) + + '=========================== INITIALIZE PIDs ========================== + FOR i=1 TO par_22 + pidn = DATA_24[i] + pid_P[pidn] = DATA_25[i] + pid_I[pidn] = DATA_26[i] + pid_D[pidn] = DATA_27[i] + pid_min[pidn] = DATA_28[i] + pid_max[pidn] = DATA_29[i] + NEXT i + '=========================== OTHER SETTINGS ========================== @@ -207,13 +217,8 @@ init: 'Determine indices for analog data acquisition ain_index[1] = 1 - ain_rate[1] = Round(1e9 / PROCESSDELAY / DATA_19[1]) FOR i=2 TO AINNO - ain_index[i] = ain_index[i-1] + ((DATA_8[i-1] - DATA_7[i-1]) / ain_rate[i-1]) - IF (Mod(DATA_8[i-1] - DATA_7[i-1],ain_rate[i-1]) <> 0) THEN - ain_index[i] = ain_index[i] + 1 - ENDIF - ain_rate[i] = Round(1e9 / PROCESSDELAY / DATA_19[i]) + ain_index[i] = ain_index[i-1] + DATA_8[i-1] - DATA_7[i-1] NEXT i @@ -246,11 +251,6 @@ init: EVENT: timer = Read_Timer_Sync() - 'Synchronize DIO Channels - if(processIdx = 20) then - P2_set_par(DIO1,1,20,1) 'starte tico event Modul 1 - P2_set_par(DIO2,1,20,1) 'starte tico event Modul 5 - endif '======================== READ ANALOG IN CARDS ========================= @@ -260,42 +260,12 @@ EVENT: 'Start conversion at all ADC Channels Synced for next Event P2_Sync_All(001100b) - - '====================== CALCULATE NEW SET VALUES ======================= - - FOR i=1 TO AOUTNO - pidn = set_pid[i] - if (pidn = 0) then - 'No PID active - set_output[i]=set_target[i] - else - 'Get deviation from target voltage - pid_error = set_target[i]- act_values[pidn] - 'Get proportional part - pid_lin=pid_P[pidn]*pid_error - 'Get integral part - pid_sum[i] = pid_sum[i] + pid_I[pidn]*pid_error - 'Get differential part - pid_dError = pid_D[pidn]* pid_error - pid_diff = pid_dError - pid_prev_dError[i] - pid_prev_dError[i] = pid_dError - - 'Check for integral overflow - if (pid_sum[i] > N) then pid_sum[i] = N - if (pid_sum[i] < -N) then pid_sum[i] = -N - - set_output[i]=(pid_lin+pid_sum[i]+pid_diff) + N - ' Check that output is within safe limits - if (set_output[i] < pid_min[pidn]) then set_output[i] = pid_min[pidn] - if (set_output[i] > pid_max[pidn]) then set_output[i] = pid_max[pidn] - endif - NEXT i - - - '========================= SET NEW AOUT VALUES ========================= - 'Write values to AOUT Cards - P2_Write_DAC8(AOUT1,set_output,1) - P2_Write_DAC8(AOUT2,set_output,9) + + 'Synchronize DIO Channels (once after 20 events) + if(processIdx = 20) then + P2_set_par(DIO1,1,20,1) 'starte tico event Modul 1 + P2_set_par(DIO2,1,20,1) 'starte tico event Modul 5 + endif 'Set all voltages synchronously P2_Sync_All(110000b) @@ -306,10 +276,8 @@ EVENT: FOR i=1 to AINNO IF(processIdx < DATA_8[i]) THEN IF (processIdx >= DATA_7[i]) THEN - ' IF (Mod(processIdx-DATA_7[i], ain_rate[i]) = 0) THEN DATA_199[ain_index[i]]=act_values[i] inc ain_index[i] - ' ENDIF ENDIF 'processIdx > DATA_7[i] ENDIF 'processIdx <= DATA_8[i] NEXT i @@ -329,30 +297,70 @@ EVENT: UNTIL(DATA_1[eventIdx+1] > processIdx) nextAOutTime = DATA_1[eventIdx+1] ENDIF + + + '====================== CALCULATE NEW SET VALUES (PIDs) ======================= + + FOR i=1 TO AOUTNO + pidn = set_pid[i] + if (pidn = 0) then + 'No PID active + set_output[i]=set_target[i] + else + 'Get deviation from target voltage + pid_error = set_target[i]- act_values[pidn] + 'Get proportional part + pid_lin=pid_P[pidn]*pid_error + 'Get integral part + pid_sum[i] = pid_sum[i] + pid_I[pidn]*pid_error + 'Get differential part + pid_dError = pid_D[pidn]* pid_error + pid_diff = pid_dError - pid_prev_dError[i] + pid_prev_dError[i] = pid_dError + + 'Check for integral overflow + if (pid_sum[i] > N) then pid_sum[i] = N + if (pid_sum[i] < -N) then pid_sum[i] = -N + + set_output[i]=(pid_lin+pid_sum[i]+pid_diff) + N + ' Check that output is within safe limits + if (set_output[i] < pid_min[pidn]) then set_output[i] = pid_min[pidn] + if (set_output[i] > pid_max[pidn]) then set_output[i] = pid_max[pidn] + endif + NEXT i '========================== Update pid target ========================== IF(nextPidTime <= processIdx) Then DO inc pidIdx i = DATA_5[pidIdx] ' output channel index - set_pid[i] = DATA_6[pidIdx] - pid_error = set_target[i] - act_values[DATA_6[pidIdx]] - pid_sum[i] = pid_sum[i] + DATA_26[pidIdx]*pid_error + set_pid[i] = DATA_6[pidIdx] ' input/PID channel index pid_prev_dError[i] = 0 + + IF (set_pid[i]=0) THEN ' When we turn off PID, use the last output value as the new target value. ' With this we can turn a beam off and on with the previous power during one shot. - set_target[i] = set_output[i] + IF (DATA_30[pidIdx]=100000) THEN set_target[i] = set_output[i] + ELSE + ' Set output value when PID is tunred on. Because we don't have an input value yet, use just the I part. + ' (Either the I value from the previous PID time, or the one set in Data_30. + IF (DATA_30[pidIdx] = 100000) THEN + set_output[i] = pid_sum[i] + N + ELSE + set_output[i] = DATA_30[pidIdx] + pid_sum[i] = set_output[i] - N + ENDIF ENDIF - i = DATA_6[pidIdx] ' input/PID channel index - pid_P[i] = DATA_25[pidIdx] - pid_I[i] = DATA_26[pidIdx] - pid_D[i] = DATA_27[pidIdx] - pid_min[i] = DATA_28[pidIdx] - pid_max[i] = DATA_29[pidIdx] + UNTIL(DATA_4[pidIdx+1] > processIdx) nextPidTime = DATA_4[pidIdx+1] ENDIF + + '========================= SET AOUT VALUES ========================= + 'Write values to AOUT Cards + P2_Write_DAC8(AOUT1,set_output,1) + P2_Write_DAC8(AOUT2,set_output,9) '### Debug Timer timer=READ_TIMER_SYNC() - timer diff --git a/README.md b/README.md index 3005a51c089c5581efff7efb59daacfcf42c9b79..837adae971c13a6444d51886dd73aa6b2ce103da 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ The global variables in the ADwin can be used for data transfer with the compute | Par_15 | Process index, updated every event loop | | Par_20 | Tico Process status of *DIO2* at end of shot, running (fine) = 1, stopped (error) = 0 | | Par_21 | PID No. which gets its parameters set from GUI | +| Par_22 | Total numbers of PIDs with settings, that are set in the INIT block | | Par_91 | Digital output of DIO1 for *manual programming* | | Par_92 | Digital output of DIO2 for *manual programming* | | FPar_21 | Value set from GUI for `pid_P[Par_21]` | @@ -47,9 +48,16 @@ The global variables in the ADwin can be used for data transfer with the compute | Data_9 | Gain modes for 16 Analog Input channels | | Data_10 | Time for digital outputs of DIO1 (in number of *TiCo* process cycles) | | Data_11 | **Digital** output bitfield for 32 channels of DIO1 at time from Data_10 | -| Data_19 | Storage rate for Analog Input channels | +| Data_19 | Storage rate for Analog Input channels (depreciated) | | Data_20 | Time for digital outputs of DIO2 (in number of *TiCo* process cycles) | | Data_21 | **Digital** output bitfield for 32 channels of DIO2 at time from Data_10 | +| Data_24 | PID channel for config | +| Data_25 | P gain of PID in Data_24 | +| Data_26 | I gain of PID in Data_24 | +| Data_27 | D gain of PID in Data_24 | +| Data_28 | Lower bound of PID in Data_24 | +| Data_29 | Upper bound of PID in Data_24 | +| Data_30 | Start value of PID at time Data_4 for AnalogOut in Data_5 | | Data_31 | Workload array for testing | | Data_93 | Analog input of AIN1 for *manual programming* | | Data_94 | Analog input of AIN2 for *manual programming* | diff --git a/Tico_DIO32.bas b/Tico_DIO32.bas index 44bcd3816534f4d4f9f070a6532cae629173703e..d86183510e2f84f3974b14a60a8f53b8e02d0688 100644 --- a/Tico_DIO32.bas +++ b/Tico_DIO32.bas @@ -7,7 +7,7 @@ ' TiCoBasic_Version = 1.6.4 ' Optimize = Yes ' Optimize_Level = 2 -' Info_Last_Save = ATI098-60 ATI098-60\labuser +' Info_Last_Save = QI-ADWIN QI-ADWIN\labuser '<Header End> @@ -27,6 +27,7 @@ INIT: UNTIL (par_20=1) 'nops(0) 'for tico module 2 (started second) nops(8) 'for tico module 1 (started first) + sleep(5) Event: