This is the VESC-integration of [lispBM](https://github.com/svenssonjoel/lispBM) written by Joel Svensson. It allows the VESC to run lisp-programs in a sandboxed environment.
### Feature Overview
* Development and testing in VESC Tool with variable live monitoring and plotting as well as CPU and memory monitoring.
* Sandboxed environment, meaning that the Lisp code (hopefully) cannot freeze or crash the rest of the VESC code when it gets stuck or runs out of heap or stack memory.
* The application runs on the VESC itself without the need for having VESC Tool connected and is stored in flash memory.
* When a lisp-application is written to the VESC it is automatically started on each boot.
Basics about LispBM are documented [here](http://svenssonjoel.github.io/lbmdoc/html/lbmref.html). The VESC-specific extensions are documented in this section. Note that VESC Tool includes a collection of examples that can be used as a starting point for using lisp on the VESC.
Reset the timeout that stops the motor. This has to be run on at least every second to keep the motor running. The timeout time can be configured in App Settings->General.
Note that control type can be set to Off in the PPM app to get the input without running the motor automatically, which is useful when running the motor from lisp.
(get-bms-val "temp_adc_num") ; Temperature sensor count
(get-bms-val "temps_adc" 2) ; Get sensor 3 temperature (index starts from 0)
(get-bms-val "temp_ic") ; Balance IC temperature
(get-bms-val "temp_hum") ; Humidity sensor temperature
(get-bms-val "hum") ; Humidity
(get-bms-val "temp_cell_max") ; Maximum cell temperature
(get-bms-val "soc") ; State of charge (0.0 to 1.0)
(get-bms-val "can_id") ; CAN ID of BMS
(get-bms-val "ah_cnt_chg_total") ; Total ah charged
(get-bms-val "wh_cnt_chg_total") ; Total wh charged
(get-bms-val "ah_cnt_dis_total") ; Total ah discharged
(get-bms-val "wh_cnt_dis_total") ; Total wh discharged
(get-bms-val "msg_age") ; Age of last message from BMS in seconds
```
#### get-adc
```clj
(get-adc ch)
```
Get ADC voltage on channel ch (0, 1 or 2).
#### systime
```clj
(systime)
```
Get system time in ticks since boot. Every tick is 0.1 ms.
#### secs-since
```clj
(secs-since timestamp)
```
Get seconds elapsed since systime timestamp.
#### set-aux
```clj
(set-aux ch state)
```
Set AUX output ch (1 or 2) to state. Example:
```clj
(set-aux 1 1) ; Set AUX1 to ON.
```
Note: The AUX output mode must be set to Unused in Motor Settings->General->Advanced. Otherwise the firmware will change the AUX state directly after it is set using this function.
Set motor current relative to the maximum current. Range -1 to 1. For example, if the maximum current is set to 50A, (set-current-rel 0.5) will set the current to 25A.
Get motor current. Positive means that current is flowing into the motor and negative means that current is flowing out of the motor (regenerative braking).
Get directional current. Positive for torque in the forward direction and negative for torque in the reverse direction.
#### get-current-in
```clj
(get-current-in)
```
Get input current. Will always be lower than the motor current. The closer the motor spins to full speed the closer the input current is to the motor current.
Get the distance traveled since start in meters. As with (get-speed) this requires that the number of motor poles, wheel diameter and gear ratio are set up correctly.
Notice that all canget-commands rely on the status messages being active on the VESCs on the CAN-bus. That can be done from App Settings->General->Can status message mode.
Get MOSFET temperature over CAN-bus on VESC with id.
#### canget-temp-motor
```clj
(canget-temp-motor id)
```
Get motor temperature over CAN-bus on VESC with id.
#### canget-speed
```clj
(canget-speed id)
```
Get speed in meters per second over CAN-bus on VESC with id. The gearing, wheel diameter and number of motor poles from the local configuration will be used for converting the RPM to meters per second.
#### canget-dist
```clj
(canget-dist id)
```
Get distance traveled in meters over CAN-bus on VESC with id. As with (canget-speed id), the local configuration will be used to convert the tachometer value to meters.
#### can-list-devs
```clj
(can-list-devs)
```
List CAN-devices that have been heard on the CAN-bus since boot. This function is fast as it does not actively scan the CAN-bus, but it relies on the devices sending status message 1.
#### can-scan
```clj
(can-scan)
```
Actively scan the CAN-bus and return a list with devices that responded. This function takes several seconds to run, but also finds devices that do not actively send messages and only respond to a ping message.
Send standard ID CAN-frame with id and data. Data is a list with bytes, and the length of the list (max 8) decides how many data bytes are sent. Example:
```clj
(can-send-sid 0x11FF11 (list 0xAA 0x11 0x15))
```
#### can-send-eid
```clj
(can-send-eid id data)
```
Same as (can-send-sid), but sends extended ID frame.
Put bits of number in initial at offset and return the result. For example, if the bits initial are aaaaaaaa, number is bbb, offset is 2 and bits is 3 the result is aaabbbaa. For reference, the corresponding operation in C is:
Return size bits of value at offset. For example if the bits of value are abcdefgh, offset is 3 and size it 3 a number with the bits cde is returned. The corresponding operation in C is:
Raw data commands useful for debugging hardware issues.
#### raw-adc-current
```clj
(raw-adc-current motor phase useRaw)
```
Get raw current measurements. Motor is the motor index (1 or 2), phase is the phase (1, 2 or 3) and useRaw is whether to convert the measurements to currents or to use raw ADC values.
Example for reading phase B on motor 1 as raw ADC values:
```clj
(raw-adc-current 1 2 1)
```
#### raw-adc-voltage
```clj
(raw-adc-voltage motor phase useRaw)
```
Same as (raw-adc-current), but measures phase voltages instead.
Same as (raw-mod-alpha), but derives the modulation from the phase voltage reading and/or dead-time compensation.
#### raw-mod-beta-measured
```clj
(raw-mod-beta-measured)
```
Same as (raw-mod-beta), but derives the modulation from the phase voltage reading and/or dead-time compensation.
#### raw-hall
```clj
(raw-hall motor optSamples)
```
Read hall sensors for motor (1 or 2) and return their states in a list. The optional argument optSamples (max 20) can be used to set how many times the hall sensors are sampled; if it is not supplied the number of samples from the motor configuration will be used.
The function (ix ind list) can be used to get an element from the list. Example:
```clj
(ix 0 (raw-hall 1)) ; Get hall sensor 1 state (index 0)
Events can be used to execute code for certain events, such as when CAN-frames are received. To use events you must first register an event handler, then enable the events you want to receive. As the event handler blocks until the event arrives it is useful to spawn a thread to handle events so that other things can be done in the main thread at the same time.
The first command might fail if it already is added, but the second one should still work. If there are uncomitted changes you can run **git stash** before the commands and **git stash pop** after them.