me2046 update
This commit is contained in:
parent
9db283927a
commit
042d46b474
@ -1,78 +1,71 @@
|
|||||||
|
function partialVals = successiveApproxADC_Partial(x, nBits, minVal, maxVal, nSplits)
|
||||||
function bitGroups = SAR_ADC_approx(x, nBits, minVal, maxVal, nSplits)
|
% SUCCESSIVEAPPROXADC_PARTIAL Simulate an n-bit SAR ADC with k partial codes,
|
||||||
% SUCCESSIVEAPPROXADC Simulate an n-bit ADC with k successive-approximation steps.
|
% then map each back into the original input range.
|
||||||
%
|
%
|
||||||
% bitGroups = successiveApproxADC(x, nBits, minVal, maxVal, nSplits)
|
% partialVals = successiveApproxADC_Partial(x, nBits, minVal, maxVal, nSplits)
|
||||||
%
|
%
|
||||||
% Inputs:
|
% Inputs:
|
||||||
% x - scalar sensor reading (double) in [minVal, maxVal]
|
% x - scalar sensor reading in [minVal, maxVal]
|
||||||
% nBits - total ADC resolution (integer ≥ 1)
|
% nBits - total ADC resolution (integer ≥ 1)
|
||||||
% minVal - ADC lower input bound (e.g. -0.25)
|
% minVal - lower bound of sensor range (e.g. -0.25)
|
||||||
% maxVal - ADC upper input bound (e.g. 1.25)
|
% maxVal - upper bound of sensor range (e.g. 1.25)
|
||||||
% nSplits - number of successive bit groups (integer between 1 and nBits)
|
% nSplits - how many successive-approximation groups you want (1…nBits)
|
||||||
%
|
%
|
||||||
% Output:
|
% Output:
|
||||||
% bitGroups - 1×nSplits cell array. Each cell{i} is a 1×groupSize vector
|
% partialVals - 1×nSplits vector of doubles in [minVal,maxVal].
|
||||||
% containing the next-most-significant bits (0 or 1).
|
% partialVals(i) corresponds to the analog voltage (or
|
||||||
|
% radians) you'd read after the first i SAR steps,
|
||||||
|
% with all remaining LSBs = 0.
|
||||||
%
|
%
|
||||||
% Steps:
|
% Method:
|
||||||
% 1) Normalize x into [0…1]
|
% 1) Normalize x into [0,1] and scale → integer code ∈ [0,2^nBits–1].
|
||||||
% 2) Scale to integer code in [0…2^nBits-1], rounding and clamping
|
% 2) Partition the n bits into nSplits groups.
|
||||||
% 3) Extract all nBits into a numeric vector with MSB first
|
% 3) For each split i:
|
||||||
% 4) Evenly partition that vector into nSplits groups
|
% – Zero out the lower (nBits – bitsUsed) bits to get partial code.
|
||||||
|
% – Convert that code back to a [0,1] fraction.
|
||||||
|
% – Rescale into [minVal,maxVal].
|
||||||
%
|
%
|
||||||
% Example:
|
% Example:
|
||||||
% % simulate a 10-bit ADC on x=0.5 in your range, split into 3 steps:
|
% pVals = successiveApproxADC_Partial(0.5, 10, -0.25, 1.25, 3);
|
||||||
% groups = successiveApproxADC(0.5, 10, -0.25, 1.25, 3);
|
% % pVals might be [0.000, 0.500, 0.683] (in radians)
|
||||||
% % display each group's bits:
|
|
||||||
% for k = 1:3
|
|
||||||
% fprintf('Step %d bits: %s\n', k, num2str(groups{k},'%d'));
|
|
||||||
% end
|
|
||||||
%
|
|
||||||
% See also bitget, dec2bin, typecast
|
|
||||||
|
|
||||||
%%— 1) Validate inputs —
|
%— 1) Validate inputs —
|
||||||
validateattributes(x, {'numeric'},{'scalar','finite'}, mfilename,'x',1);
|
validateattributes(x, {'numeric'},{'scalar','finite'}, mfilename,'x',1);
|
||||||
validateattributes(nBits, {'numeric'},{'scalar','integer','>=',1}, mfilename,'nBits',2);
|
validateattributes(nBits, {'numeric'},{'scalar','integer','>=',1}, mfilename,'nBits',2);
|
||||||
validateattributes(minVal, {'numeric'},{'scalar','finite'}, mfilename,'minVal',3);
|
validateattributes(minVal, {'numeric'},{'scalar','finite'}, mfilename,'minVal',3);
|
||||||
validateattributes(maxVal, {'numeric'},{'scalar','finite','>',minVal}, mfilename,'maxVal',4);
|
validateattributes(maxVal, {'numeric'},{'scalar','finite','>',minVal}, mfilename,'maxVal',4);
|
||||||
validateattributes(nSplits,{'numeric'},{'scalar','integer','>=',1,'<=',nBits}, ...
|
validateattributes(nSplits, {'numeric'},{'scalar','integer','>=',1,'<=',nBits}, ...
|
||||||
mfilename,'nSplits',5);
|
mfilename,'nSplits',5);
|
||||||
|
|
||||||
%%— 2) Map x into the ADC code range —
|
%— 2) Compute full ADC code (integer) from x —
|
||||||
% normalize into [0,1]
|
normX = (x - minVal) / (maxVal - minVal); % [0…1]
|
||||||
normX = (x - minVal) / (maxVal - minVal);
|
rawCode = normX * (2^nBits - 1); % [0…2^nBits-1]
|
||||||
|
code = round(rawCode); % nearest integer
|
||||||
|
code = min(max(code, 0), 2^nBits - 1); % clamp
|
||||||
|
|
||||||
% scale to [0…2^nBits-1]
|
uCode = uint64(code); % for bit operations
|
||||||
rawCode = normX * (2^nBits - 1);
|
|
||||||
|
|
||||||
% round to nearest integer
|
%— 3) Determine group sizes for the nSplits —
|
||||||
code = round(rawCode);
|
baseSize = floor(nBits / nSplits);
|
||||||
|
leftover = mod(nBits, nSplits);
|
||||||
|
groupSizes = [ repmat(baseSize+1, 1, leftover), ...
|
||||||
|
repmat(baseSize, 1, nSplits-leftover) ];
|
||||||
|
|
||||||
% clamp just in case x was slightly outside
|
%— 4) Loop over splits, build partial codes, then scale back —
|
||||||
% This also makes the SAR ADC have a saturating behavior
|
partialVals = zeros(1, nSplits);
|
||||||
code = min( max(code, 0), 2^nBits - 1 );
|
bitsUsed = 0;
|
||||||
|
for i = 1:nSplits
|
||||||
|
bitsUsed = bitsUsed + groupSizes(i); % total MSBs now included
|
||||||
|
dropBits = nBits - bitsUsed; % LSBs to zero
|
||||||
|
|
||||||
%%— 3) Convert to an nBits-long vector of 0/1, MSB first —
|
% a) keep only the top bitsUsed bits:
|
||||||
% bitget treats position 1 as LSB, so we ask for positions nBits:-1:1
|
msPart = bitshift(uCode, -dropBits);
|
||||||
bitIdx = nBits:-1:1;
|
% b) shift back to full width, zeroing lower bits:
|
||||||
bitsVec = bitget(code, bitIdx);
|
pc = bitshift(msPart, dropBits);
|
||||||
|
|
||||||
% now bitsVec(1) is the single MSB, bitsVec(end) is the LSB
|
% c) map pc (∈[0…2^nBits–1]) back to [0,1]:
|
||||||
|
frac = double(pc) / double(2^nBits - 1);
|
||||||
%%— 4) Partition into nSplits groups —
|
% d) rescale into [minVal,maxVal]:
|
||||||
baseSize = floor(nBits / nSplits); % minimum bits per group
|
partialVals(i) = frac * (maxVal - minVal) + minVal;
|
||||||
extra = mod(nBits, nSplits); % leftover bits
|
|
||||||
% first 'extra' groups get one extra bit to distribute evenly
|
|
||||||
groupSizes = [ repmat(baseSize+1, 1, extra), ...
|
|
||||||
repmat(baseSize, 1, nSplits-extra) ];
|
|
||||||
|
|
||||||
bitGroups = cell(1, nSplits);
|
|
||||||
idx = 1;
|
|
||||||
for k = 1 : nSplits
|
|
||||||
sz = groupSizes(k);
|
|
||||||
bitGroups{k} = bitsVec(idx : idx + sz - 1);
|
|
||||||
idx = idx + sz;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@ -30,8 +30,10 @@ Ts_third_register = Ts_whole_register/3;
|
|||||||
sys_third_register = c2d(sys_cont, Ts_third_register, 'zoh');
|
sys_third_register = c2d(sys_cont, Ts_third_register, 'zoh');
|
||||||
|
|
||||||
% Create a Reference Signal
|
% Create a Reference Signal
|
||||||
[ref, t, N] = make_hdd_reference(0.1, Ts_whole_register, 1e-2, 42);
|
max_time = 1e-2;
|
||||||
[ref_third, t_third, N_third] = make_hdd_reference(0.1, Ts_third_register, 1e-2, 42);
|
[ref, t, N] = make_hdd_reference(max_time, Ts_whole_register, 1e-2, 42);
|
||||||
|
|
||||||
|
[ref_third, t_third, N_third] = make_hdd_reference(9*Ts_third_register, Ts_third_register, 1e-2, 42);
|
||||||
|
|
||||||
%% Running a Simulation
|
%% Running a Simulation
|
||||||
% ADC Delay, no sub-steps - Setting Up Simulation
|
% ADC Delay, no sub-steps - Setting Up Simulation
|
||||||
@ -47,9 +49,12 @@ opts.plotting = false;
|
|||||||
[x_hist, y_hist, u_hist, x_hat_hist] = solve_full_step(opts);
|
[x_hist, y_hist, u_hist, x_hat_hist] = solve_full_step(opts);
|
||||||
|
|
||||||
% ADC delay, with sub-steps
|
% ADC delay, with sub-steps
|
||||||
|
opts.K = [0.7+1e-4i 0.7-1e-4i];
|
||||||
|
opts.L = [0.4+0.01i 0.4-0.01i];
|
||||||
opts.sys = sys_third_register;
|
opts.sys = sys_third_register;
|
||||||
opts.sub_steps = 3;
|
opts.sub_steps = 3;
|
||||||
opts.r = ref_third;
|
opts.r = ref_third;
|
||||||
|
opts.N = N_third/3;
|
||||||
opts.res = 12;
|
opts.res = 12;
|
||||||
opts.plotting = true;
|
opts.plotting = true;
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ function [x_hist, y_hist, u_hist, x_hat_hist] = solve_sub_step(opts)
|
|||||||
% ▸ L – observer gain matrix
|
% ▸ L – observer gain matrix
|
||||||
% ▸ K – state‑feedback gain matrix
|
% ▸ K – state‑feedback gain matrix
|
||||||
% ▸ r – reference trajectory [nu × N]
|
% ▸ r – reference trajectory [nu × N]
|
||||||
% ▸ sub_step – number of sub_steps per sample
|
% ▸ sub_steps – number of sub_steps per sample
|
||||||
% ▸ res – number of bits of resolution
|
% ▸ res – number of bits of resolution
|
||||||
|
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ N = opts.N;
|
|||||||
L = transpose(place(sys.A', sys.C', opts.L));
|
L = transpose(place(sys.A', sys.C', opts.L));
|
||||||
K = place(sys.A, sys.B, opts.K);
|
K = place(sys.A, sys.B, opts.K);
|
||||||
r = opts.r;
|
r = opts.r;
|
||||||
J = opts.sub_step;
|
J = opts.sub_steps;
|
||||||
res = opts.res;
|
res = opts.res;
|
||||||
plotting = opts.plotting;
|
plotting = opts.plotting;
|
||||||
|
|
||||||
@ -58,18 +58,17 @@ Ts = sys.Ts;
|
|||||||
ny = size(C,1);
|
ny = size(C,1);
|
||||||
|
|
||||||
% ----------------‑‑ Pre‑allocate histories -----------------------------
|
% ----------------‑‑ Pre‑allocate histories -----------------------------
|
||||||
x_hist = zeros(nx,(N+1)*J);
|
x_hist = zeros(nx,N*J+1);
|
||||||
y_hist = zeros(ny,N*J);
|
y_hist = zeros(ny,N*J);
|
||||||
u_hist = zeros(nu,N*J);
|
u_hist = zeros(nu,N*J);
|
||||||
|
|
||||||
x_hist(:,1:1*J) = x0;
|
x_hist(:,1) =x0; % Observer bookkeeping
|
||||||
|
|
||||||
% Observer bookkeeping
|
|
||||||
useObserver = ~isempty(L);
|
useObserver = ~isempty(L);
|
||||||
if useObserver
|
if useObserver
|
||||||
fprintf('Observer enabled.\n');
|
fprintf('Observer enabled.\n');
|
||||||
x_hat = [0;0];
|
x_hat = [0;0];
|
||||||
x_hat_hist = zeros(nx,N+1);
|
x_hat_hist = zeros(nx,N*J+1);
|
||||||
x_hat_hist(:,1) = x_hat;
|
x_hat_hist(:,1) = x_hat;
|
||||||
else
|
else
|
||||||
x_hat_hist = [];
|
x_hat_hist = [];
|
||||||
@ -84,36 +83,62 @@ if ~useFB && isempty(u)
|
|||||||
end
|
end
|
||||||
|
|
||||||
% Ensure reference is sized correctly if provided
|
% Ensure reference is sized correctly if provided
|
||||||
if ~isempty(r) && size(r,2)~=N
|
if ~isempty(r) && size(r,2)~=J*N
|
||||||
error('opts.r must have N columns.');
|
error('opts.r must have J*N columns.');
|
||||||
end
|
end
|
||||||
|
|
||||||
% ----------------‑‑ Simulation loop ------------------------------------
|
% ----------------‑‑ Simulation loop ------------------------------------
|
||||||
for k = 1:N-1
|
for k = (1:J:(N-1)*J)%N-1
|
||||||
|
k
|
||||||
|
x_hist(:,k+1) = A*x_hist(:,k+0) + B*u_hist(k+0);
|
||||||
|
y_hist(:,k+0) = C*x_hist(:,k+0);
|
||||||
|
|
||||||
%ASSUME SENSOR RANGE OF 0-1 RAD -> 0 -> 2^12
|
%ASSUME SENSOR RANGE OF 0-1 RAD -> 0 -> 2^12
|
||||||
sensor_value = y_hist(:,k)*2^res;
|
sensor_value = y_hist(:,k+0)*2^res;
|
||||||
ADC_output = SAR_ADC_approx(sensor_value, res, -0.2, 1.2, J);
|
ADC_output = SAR_ADC_approx(sensor_value, res, -0.2, 1.2, J);
|
||||||
|
|
||||||
%FIRST SUBSTEP
|
%FIRST SUBSTEP
|
||||||
x_hat =
|
|
||||||
x_hat_hist(:,J*k+1) = A*
|
|
||||||
|
|
||||||
% Compute input
|
x_hat_hist(:,k+1) = A*x_hat_hist(:,k+0) + ...
|
||||||
u_k = K*(-x_hat_hist(:,k) + (isempty(r) * 0 + ~isempty(r) * r(:,k)));
|
B*u_hist(k+0) + ...
|
||||||
u_hist(k) = u_k;
|
L*( ADC_output(1) - C*x_hat_hist(:,k+0));
|
||||||
|
|
||||||
% Plant output
|
u_hist(k+1) = K*(r(:,k+1)-x_hat_hist(:,k+1));
|
||||||
y_hist(:,k+1) = C*x_hist(:,k) + D*u_k; %SHIFT RIGHT TO INDUCE DELAY
|
|
||||||
|
|
||||||
% Propagate observer states
|
%SECOND SUBSTEP
|
||||||
x_hat = A*x_hat + B*u_k + L*(y_hist(:,k) - C*x_hat - D*u_k);
|
x_hist(:,k+2) = A*x_hist(:,k+1) + B*u_hist(k+1);
|
||||||
x_hat_hist(:,k+1) = x_hat;
|
y_hist(:,k+1) = C*x_hist(:,k+1);
|
||||||
|
|
||||||
%Calculate Next State
|
x_hat_hist(:,k+2) = A*(A*x_hat_hist(:,k+0) + ...
|
||||||
x_hist(:,k+1) = A*x_hist(:,k) + B*u_k;
|
B*u_hist(k+0) + ...
|
||||||
|
L*(ADC_output(2) - C*x_hat_hist(:,k+0))...
|
||||||
|
) + ...
|
||||||
|
B*u_hist(k+1);
|
||||||
|
|
||||||
|
u_hist(k+2) = K*(r(:,k+2)-x_hat_hist(:,k+2));
|
||||||
|
|
||||||
|
%THIRD SUBSTEP
|
||||||
|
x_hist(:,k+3) = A*x_hist(:,k+2) + B*u_hist(k+2);
|
||||||
|
y_hist(:,k+2) = C*x_hist(:,k+2);
|
||||||
|
|
||||||
|
x_hat_hist(:,k+3) = A*(A*(A*x_hat_hist(:,k+0) + ...
|
||||||
|
B*u_hist(k+0) + ...
|
||||||
|
L*(ADC_output(3) - C*x_hat_hist(:,k+0))...
|
||||||
|
) + ...
|
||||||
|
B*u_hist(k+1)...
|
||||||
|
) + ...
|
||||||
|
B*u_hist(k+2);
|
||||||
|
|
||||||
|
u_hist(k+3) = K*(r(:,k+3)-x_hat_hist(:,k+3));
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
x_hist
|
||||||
|
x_hat_hist
|
||||||
|
y_hist
|
||||||
|
u_hist
|
||||||
|
|
||||||
|
|
||||||
% ----------------‑‑ Plot results ---------------------------------------
|
% ----------------‑‑ Plot results ---------------------------------------
|
||||||
|
|
||||||
if plotting
|
if plotting
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user