Compare commits
4 Commits
97490e5e1b
...
11f2ebe961
Author | SHA1 | Date |
---|---|---|
Astro | 11f2ebe961 | |
Astro | 4b75c6147d | |
Astro | 445cde6ae8 | |
Astro | 6951489545 |
|
@ -28,6 +28,7 @@ series = {
|
||||||
'sens': Series(0.0001),
|
'sens': Series(0.0001),
|
||||||
'temperature': Series(),
|
'temperature': Series(),
|
||||||
'i_set': Series(),
|
'i_set': Series(),
|
||||||
|
'pid_output': Series(),
|
||||||
'vref': Series(),
|
'vref': Series(),
|
||||||
'dac_feedback': Series(),
|
'dac_feedback': Series(),
|
||||||
'i_tec': Series(),
|
'i_tec': Series(),
|
||||||
|
@ -39,7 +40,6 @@ series_lock = Lock()
|
||||||
quit = False
|
quit = False
|
||||||
|
|
||||||
def recv_data(tec):
|
def recv_data(tec):
|
||||||
print("reporting")
|
|
||||||
for data in tec.report_mode():
|
for data in tec.report_mode():
|
||||||
if data['channel'] == 0:
|
if data['channel'] == 0:
|
||||||
series_lock.acquire()
|
series_lock.acquire()
|
||||||
|
@ -56,7 +56,6 @@ def recv_data(tec):
|
||||||
break
|
break
|
||||||
|
|
||||||
tec = Client()
|
tec = Client()
|
||||||
print("connected")
|
|
||||||
thread = Thread(target=recv_data, args=(tec,))
|
thread = Thread(target=recv_data, args=(tec,))
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
|
@ -64,15 +63,17 @@ fig, ax = plt.subplots()
|
||||||
|
|
||||||
for k, s in series.iteritems():
|
for k, s in series.iteritems():
|
||||||
s.plot, = ax.plot([], [], label=k)
|
s.plot, = ax.plot([], [], label=k)
|
||||||
ax.legend()
|
legend = ax.legend()
|
||||||
|
|
||||||
def animate(i):
|
def animate(i):
|
||||||
min_x, max_x, min_y, max_y = None, None, None, None
|
min_x, max_x, min_y, max_y = None, None, None, None
|
||||||
|
|
||||||
series_lock.acquire()
|
series_lock.acquire()
|
||||||
try:
|
try:
|
||||||
for s in series.itervalues():
|
for k, s in series.iteritems():
|
||||||
s.plot.set_data(s.x_data, s.y_data)
|
s.plot.set_data(s.x_data, s.y_data)
|
||||||
|
if len(s.y_data) > 0:
|
||||||
|
s.plot.set_label("{}: {:.3f}".format(k, s.y_data[-1]))
|
||||||
|
|
||||||
if len(s.x_data) > 0:
|
if len(s.x_data) > 0:
|
||||||
min_x_ = min(s.x_data)
|
min_x_ = min(s.x_data)
|
||||||
|
@ -107,21 +108,13 @@ def animate(i):
|
||||||
ax.set_xlim(min_x, max_x)
|
ax.set_xlim(min_x, max_x)
|
||||||
ax.set_ylim(min_y - margin_y, max_y + margin_y)
|
ax.set_ylim(min_y - margin_y, max_y + margin_y)
|
||||||
|
|
||||||
|
global legend
|
||||||
|
legend.remove()
|
||||||
|
legend = ax.legend()
|
||||||
|
|
||||||
ani = animation.FuncAnimation(
|
ani = animation.FuncAnimation(
|
||||||
fig, animate, interval=1, blit=False, save_count=50)
|
fig, animate, interval=1, blit=False, save_count=50)
|
||||||
|
|
||||||
# To save the animation, use e.g.
|
|
||||||
#
|
|
||||||
# ani.save("movie.mp4")
|
|
||||||
#
|
|
||||||
# or
|
|
||||||
#
|
|
||||||
# writer = animation.FFMpegWriter(
|
|
||||||
# fps=15, metadata=dict(artist='Me'), bitrate=1800)
|
|
||||||
# ani.save("movie.mp4", writer=writer)
|
|
||||||
|
|
||||||
print("show")
|
|
||||||
plt.show()
|
plt.show()
|
||||||
quit = True
|
quit = True
|
||||||
thread.join()
|
thread.join()
|
||||||
|
|
|
@ -91,6 +91,19 @@ impl Channels {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// calculate the TEC i_set centerpoint
|
||||||
|
pub fn get_center(&mut self, channel: usize) -> ElectricPotential {
|
||||||
|
match self.channel_state(channel).center {
|
||||||
|
CenterPoint::Vref => {
|
||||||
|
let vref = self.read_vref(channel);
|
||||||
|
self.channel_state(channel).vref = vref;
|
||||||
|
vref
|
||||||
|
},
|
||||||
|
CenterPoint::Override(center_point) =>
|
||||||
|
ElectricPotential::new::<volt>(center_point.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// i_set DAC
|
/// i_set DAC
|
||||||
fn get_dac(&mut self, channel: usize) -> (ElectricPotential, ElectricPotential) {
|
fn get_dac(&mut self, channel: usize) -> (ElectricPotential, ElectricPotential) {
|
||||||
let dac_factor = match channel.into() {
|
let dac_factor = match channel.into() {
|
||||||
|
@ -104,13 +117,7 @@ impl Channels {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_i(&mut self, channel: usize) -> (ElectricCurrent, ElectricCurrent) {
|
pub fn get_i(&mut self, channel: usize) -> (ElectricCurrent, ElectricCurrent) {
|
||||||
let state = self.channel_state(channel);
|
let center_point = self.get_center(channel);
|
||||||
let center_point = match state.center {
|
|
||||||
CenterPoint::Vref =>
|
|
||||||
state.vref,
|
|
||||||
CenterPoint::Override(center_point) =>
|
|
||||||
ElectricPotential::new::<volt>(center_point.into()),
|
|
||||||
};
|
|
||||||
let r_sense = ElectricalResistance::new::<ohm>(R_SENSE);
|
let r_sense = ElectricalResistance::new::<ohm>(R_SENSE);
|
||||||
let (voltage, max) = self.get_dac(channel);
|
let (voltage, max) = self.get_dac(channel);
|
||||||
let i_tec = (voltage - center_point) / (10.0 * r_sense);
|
let i_tec = (voltage - center_point) / (10.0 * r_sense);
|
||||||
|
@ -138,13 +145,7 @@ impl Channels {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_i(&mut self, channel: usize, i_tec: ElectricCurrent) -> (ElectricCurrent, ElectricCurrent) {
|
pub fn set_i(&mut self, channel: usize, i_tec: ElectricCurrent) -> (ElectricCurrent, ElectricCurrent) {
|
||||||
let state = self.channel_state(channel);
|
let center_point = self.get_center(channel);
|
||||||
let center_point = match state.center {
|
|
||||||
CenterPoint::Vref =>
|
|
||||||
state.vref,
|
|
||||||
CenterPoint::Override(center_point) =>
|
|
||||||
ElectricPotential::new::<volt>(center_point.into()),
|
|
||||||
};
|
|
||||||
let r_sense = ElectricalResistance::new::<ohm>(R_SENSE);
|
let r_sense = ElectricalResistance::new::<ohm>(R_SENSE);
|
||||||
let voltage = i_tec * 10.0 * r_sense + center_point;
|
let voltage = i_tec * 10.0 * r_sense + center_point;
|
||||||
let (voltage, max) = self.set_dac(channel, voltage);
|
let (voltage, max) = self.set_dac(channel, voltage);
|
||||||
|
@ -417,6 +418,9 @@ impl Channels {
|
||||||
let i_tec = self.read_itec(channel);
|
let i_tec = self.read_itec(channel);
|
||||||
let tec_i = (i_tec - vref) / ElectricalResistance::new::<ohm>(0.4);
|
let tec_i = (i_tec - vref) / ElectricalResistance::new::<ohm>(0.4);
|
||||||
let state = self.channel_state(channel);
|
let state = self.channel_state(channel);
|
||||||
|
let pid_output = state.pid.last_output.map(|last_output|
|
||||||
|
ElectricCurrent::new::<ampere>(last_output)
|
||||||
|
);
|
||||||
Report {
|
Report {
|
||||||
channel,
|
channel,
|
||||||
time: state.adc_time.total_millis(),
|
time: state.adc_time.total_millis(),
|
||||||
|
@ -431,6 +435,7 @@ impl Channels {
|
||||||
i_tec,
|
i_tec,
|
||||||
tec_i,
|
tec_i,
|
||||||
tec_u_meas: self.read_tec_u_meas(channel),
|
tec_u_meas: self.read_tec_u_meas(channel),
|
||||||
|
pid_output,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -449,12 +454,41 @@ pub struct Report {
|
||||||
i_tec: ElectricPotential,
|
i_tec: ElectricPotential,
|
||||||
tec_i: ElectricCurrent,
|
tec_i: ElectricCurrent,
|
||||||
tec_u_meas: ElectricPotential,
|
tec_u_meas: ElectricPotential,
|
||||||
|
pid_output: Option<ElectricCurrent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type JsonBuffer = heapless::Vec<u8, heapless::consts::U320>;
|
type JsonBuffer = heapless::Vec<u8, heapless::consts::U360>;
|
||||||
|
|
||||||
impl Report {
|
impl Report {
|
||||||
pub fn to_json(&self) -> Result<JsonBuffer, serde_json_core::ser::Error> {
|
pub fn to_json(&self) -> Result<JsonBuffer, serde_json_core::ser::Error> {
|
||||||
serde_json_core::to_vec(self)
|
serde_json_core::to_vec(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn report_to_json() {
|
||||||
|
// `/ 1.1` results in values with a really long serialization
|
||||||
|
let report = Report {
|
||||||
|
channel: 0,
|
||||||
|
time: 3200,
|
||||||
|
adc: Some(ElectricPotential::new::<volt>(0.65 / 1.1)),
|
||||||
|
sens: Some(ElectricalResistance::new::<ohm>(10000.0 / 1.1)),
|
||||||
|
temperature: Some(30.0 / 1.1),
|
||||||
|
pid_engaged: false,
|
||||||
|
i_set: ElectricCurrent::new::<ampere>(0.5 / 1.1),
|
||||||
|
vref: ElectricPotential::new::<volt>(1.5 / 1.1),
|
||||||
|
dac_feedback: ElectricPotential::new::<volt>(2.0 / 1.1),
|
||||||
|
i_tec: ElectricPotential::new::<volt>(2.0 / 1.1),
|
||||||
|
tec_i: ElectricCurrent::new::<ampere>(0.2 / 1.1),
|
||||||
|
tec_u_meas: ElectricPotential::new::<volt>(2.0 / 1.1),
|
||||||
|
pid_output: Some(ElectricCurrent::new::<ampere>(0.5 / 1.1)),
|
||||||
|
};
|
||||||
|
let buf = report.to_json().unwrap();
|
||||||
|
assert_eq!(buf[0], b'{');
|
||||||
|
assert_eq!(buf[buf.len() - 1], b'}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use crate::usb;
|
||||||
pub fn init_log() {
|
pub fn init_log() {
|
||||||
static USB_LOGGER: usb::Logger = usb::Logger;
|
static USB_LOGGER: usb::Logger = usb::Logger;
|
||||||
let _ = log::set_logger(&USB_LOGGER);
|
let _ = log::set_logger(&USB_LOGGER);
|
||||||
log::set_max_level(log::LevelFilter::Info);
|
log::set_max_level(log::LevelFilter::Trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "semihosting")]
|
#[cfg(feature = "semihosting")]
|
||||||
|
|
Loading…
Reference in New Issue