Main Module

Main script to be run automatically on raspberry Pi startup. Web requests, measurements and GPIO control occur simultaneously and independently. Concurrency based on Python 3.5’s async/await syntax with the asyncio library.

Hayley Weir, 11/12/16:
Hardware (GPIO control), pid calculation, heat ramp process
Jin Cheng, 12/12/16:
Refactored Hayley’s code into modular and asynchronous functions, event loops, futures and co-routines. Introduced web API communication functions, calorimetry and flow logic, implement current -> power conversion, documentation
Jin Cheng, 16/01/17:
Several debugging changes to simplify calibration, allow customisation of PID params, loop interval, maximum ramp rate from web interface.
Jin Cheng, 17/01/17:
Major refactor of common flow logic code into classes, optimisation of the temperature ramp logic to make temp profile as linear as possible.
robotchem.main.active(_loop, **calorimeter_data)[source]

An asynchronous coroutine run periodically during an active calorimetry job. Contains logic about the set point, heating to start temp as quickly as possible, and uploading measurements.

This function is the overarching loop responsible for two main parts of the DSC job.

  1. Firstly measure both temperatures simultaneously.
  2. Instantiate a new classes.Run object containing relevant basic info about this DSC run. The info comes from the web API JSON response in the form of a dict. This dict then constructs the classes.Run object using the special classmethod classes.Run.from_web_resp().
  3. Switch on LED lights to indicate starting up. Asynchronously, yield control to the main.get_ready() co-routine loop. Coincidentally, when a new Run object is instantiated, it will automatically set the heaters
  4. When control is given back to this function, it suggests that temperature has stabilised at the start temperature. Switch on LED lights to indicate heating up, while yielding control to the main.run_calorimetry() co-routine.
  5. When control is again yielded to this function, the DSC job in question has finished. Clean up the GPIO boards and go back to the main.idle() loop.

This function will also go back to the main.idle() loop and cleanup if at any point a utils.StopHeatingError is raised.

Parameters:
  • _loop – The main event loop.
  • calorimeter_data – JSON representation of the active job from the server API.
robotchem.main.get_ready(_loop, run)[source]

An aync function that gets the temperatures to starting temp as quickly as possible.

It first instantiate and initialise the heater PWM objects related to the classes.Run object, so that their duty cycles can be changed inside the loop.

The loop itself flows like this:

  1. Make all temperature, current measurements simultaneously. After making measurements, the classes.Run.make_measurement() method automatically updates the PID controllers with the new measurements and changes the heater PWM values. Its setpoint, though, is never changed from the starting temperature, ensuring it is reached as quickly as possible.
  2. Put measurement data into the utils.NetworkQueue queue to be uploaded to the web. After queueing, the classes.Run.queue_upload() method should check if the user has inserted the sample and prepared for the formal heat ramp.
  3. Check if the temperature has stabilised around the start temperature. If so, and if user has inserted the sample, go back to the main.active() function, which will invoke next the formal linear heat ramp.
Parameters:
  • _loop – the main event loop.
  • run – the object representing the run params.
robotchem.main.idle(_loop)[source]

An asynchronous coroutine run periodically during idle periods. Checks the web API if it should start new jobs, and updates the web API about measured temperatures.

The periodicity of refreshing and updating web API is determined by the settings.WEB_API_IDLE_INTERVAL value, or the corresponding value received from the web API.

This loop does the following:

  1. Read reference and sample temperatures (simultanouesly)
  2. Upload temperature values to the web API address specified by the settings.WEB_API_BASE_ADDRESS value.
  3. If the web response includes some basic information about a user-specified new calorimetry job, enter the main.active() loop.
  4. After the main.active() loop has finished running, this function will have control again, which suggests that the active job has ended.
  5. Renew running this loop after a certain time interval.
Parameters:_loop (asyncio.BaseEventLoop) – The main event loop.
robotchem.main.run_calorimetry(_loop, run)[source]

An async function that starts the heat ramp until the end temp is reached at the rate of choice. Periodically and transmit currents and temperatures to web API.

This loop runs similarly to the get_ready() co-routine. But in addition to PWM calculations and network queues, this loop also:

  1. Each cycle, check if temperature has ‘stabilised’ around the setpoint of the classes.Run object. Note the threshold for determining temperature stabilisation is less stringent for this purpose, because being too strict may lead to a staircase temperature profile from experience.
  2. If stabilised, increase the setpoint temperature by a ramp increment. This increment value is a fraction of the settings.MAX_RAMP_RATE value, or the corresponding setting on the web server. The exact percentage of the maximum is as specified for this particular DSC job on the website.
  3. If temperatures have stabilised around the end temperature for a specified duration, stop heating and upload the remainder of all measurement data.
Parameters:
  • _loop – the main event loop
  • run – the object representing the run params.
Raises:

StopHeatingError – raised when the end temperature has been reached for a certain amount of time.