Can you use events or interrupts with EV3 micropython? - lego-mindstorms

I am attempting to write a program for a LEGO Mindstorms EV3 brick that requires actions to be taken when a specific input is recorded by the sensors. As far as I can tell, the only way to do this in EV3 micropython / pybricks is by busy-waiting. This limits the ability to process other information whilst the sensors are checking, since the brick does seemingly not support multithreading.
It seems, however, that the EV3 Classroom block programming supports using events.
Can this be done using events in pybricks too?

You can use multithreading in pybricks using the threading module.
I used that for creating events for the touch sensor,
I didn't tested it, it is an old code that after I wrote it I realized that I don't need it.
But here is the code:
Thread(target=self.listenForButtonClick).start()
def onButtonClick(self, func):
"""
Add a function to be called when a button is clicked on the EV3 Brick.
:param func: the function to be called.
"""
self.buttonClick.append(func)
def listenForButtonClick(self):
"""
Listen for button clicks on the EV3 Brick.
"""
while True:
if any(self.buttons.pressed()):
for func in self.buttonClick:
func(self.buttons.pressed())
wait(50)
Example Usage:
def click(args):
print(args)
# Do Stuff
onButtonClick(click)

Related

How do I add a missing peripheral register to a STM32 MCU model in Renode?

I am trying out this MCU / SoC emulator, Renode.
I loaded their existing model template under platforms/cpus/stm32l072.repl, which just includes the repl file for stm32l071 and adds one little thing.
When I then load & run a program binary built with STM32CubeIDE and ST's LL library, and the code hits the initial function of SystemClock_Config(), where the Flash:ACR register is being probed in a loop, to observe an expected change in value, it gets stuck there, as the Renode Monitor window is outputting:
[WARNING] sysbus: Read from an unimplemented register Flash:ACR (0x40022000), returning a value from SVD: 0x0
This seems to be expected, not all existing templates model nearly everything out of the box. I also found that the stm32L071 model is missing some of the USARTs and NVIC channels. I saw how, probably, the latter might be added, but there seems to be not a single among the default models defining that Flash:ACR register that I could use as example.
How would one add such a missing register for this particular MCU model?
Note1: For this test, I'm using a STM32 firmware binary which works as intended on actual hardware, e.g. a devboard for this MCU.
Note2:
The stated advantage of Renode over QEMU, which does apparently not emulate peripherals, is also allowing to stick together a more complex system, out of mocked external e.g. I2C and other devices (apparently C# modules, not yet looked into it).
They say "use the same binary as on the real system".
Which is my reason for trying this out - sounds like a lot of potential for implementing systems where the hardware is not yet fully available, and also automatted testing.
So the obvious thing, commenting out a lot of parts in init code, to only test some hardware-independent code while sidestepping such issues, would defeat the purpose here.
If you want to just provide the ACR register for the flash to pass your init, use a tag.
You can either provide it via REPL (recommended, like here https://github.com/renode/renode/blob/master/platforms/cpus/stm32l071.repl#L175) or via RESC.
Assuming that your software would like to read value 0xDEADBEEF. In the repl you'd use:
sysbus:
init:
Tag <0x40022000, 0x40022003> "ACR" 0xDEADBEEF
In the resc or in the Monitor it would be just:
sysbus Tag <0x40022000, 0x40022003> "ACR" 0xDEADBEEF
If you want more complex logic, you can use a Python peripheral, as described in the docs (https://renode.readthedocs.io/en/latest/basic/using-python.html#python-peripherals-in-a-platform-description):
flash: Python.PythonPeripheral # sysbus 0x40022000
size: 0x1000
initable: false
filename: "script_with_complex_python_logic.py"
```
If you really need advanced implementation, then you need to create a complete C# model.
As you correctly mentioned, we do not want you to modify your binary. But we're ok with mocking some parts we're not interested in for a particular use case if the software passes with these mocks.
Disclaimer: I'm one of the Renode developers.

8 channel async mic recording in matlab

I wanted to record a sequence of sounds (using 8 channel mic array).
Matlab's audiorecorder system object does not support more than 2 channels async recording.
When I say async, I want to achieve the following:
The user will press some key (handled by event handler gui) it will start the recording and then again user will press a key then the system will save the current recording and user starts with next audio in the sequence.
I can record 8 ch from Matlab using audioDeviceReader system object but for that, I need to call it for each frame so I will have to create a parallel process that will have to communicate with the event handler and the audioDeviceReader.
I don't have much experience will parallel programming? Should I look into audiorecorder's code and see if can be trivially changed to support 8 ch (If that was the case I think they would have already done it). Or write code to spawn a parallel process which exposes record and stop functions wrapping over audioDeviceReader which can interface with event listener similar to audiorecorder? If so how should I proceed?
Well surprisingly removing the num channel error check in the library code worked. :)

Structured Text : Function and Function block (Pros and Cons)

I am coming from computer science background and used to traditional IT programming. I have relatively little experience with structured text. In my current project I am extensively using many function block. I am aware that this involves some memory issues and so on. Could anyone come up and give me some advantages and disadvantages of each of them. Should I avoid them and write everything in a single program ? Please practical hints should be welcome as I am about to release my application.
System : Codesys
I also come from the PC programming world, and there are certain object tricks I miss when programming in Codesys. The function blocks go a long way towards object thinking, though. They're too easy to peek into from the outside, so some discipline from the user is necessary, to encapsulate the functionality or objects.
You shouldn't write a single piece of program to handle all functionality, but instead use the Codesys facilities to divide the program into objects where possible. This also means to identify which objects are alike and can be programmed as function blocks. The instance of a function block is created in memory when the program is downloaded, e.g. it is always visible for monitoring.
I normally use POU's to divide the project into larger parts, e.g. Machine1(prg), Machine2(prg) and Machine3(prg). If each machine has one or more motors of similar type, this is where the function blocks come in, so that I can program one motor object called FB_Motor, and reuse it for the necessary motor instances inside the 3 machine programs. Each instance can then hold its own internal states, timers, input output, or whatever a motor needs.
The structure for the above example is now:
MAIN, calls
Machine1(prg), calls
fbMotor1 (implements FB_Motor, local for Machine1)
fbMotor2 (implements FB_Motor, local for Machine1)
Machine2(prg), calls
fbMotor1 (implements FB_Motor, local for Machine2)
Machine3(prg), calls
fbMotor1 (implements FB_Motor, local for Machine3)
fbMotor2 (implements FB_Motor, local for Machine3)
fbMotor3 (implements FB_Motor, local for Machine3)
The functions are another matter. Their data exist on the stack when the function is called, and when the function has returned its value, the data is released. There are lots of built in functions, e.g. BOOL_TO_INT(), SQR(n) and so on.
I normally use functions for lookup and conversion functions. And they can be called from all around the program.
The clarity, robustness and maintainability are everything in PLC world. Function blocks help you to archieve that if the stucture is kept relatively flat (so one should avoid functionblock inside functionblock insede function block, compared of true object and their heritage).
Also the graphical languages are there for reason they visualise the complex systems in easy to digest form in a way that the maintaining personnel in the future have easier life to follow what is wrong with the PLC program and the part of the factory.
What comes to ST it is advance to remember that it is based on strongly typed Wirthian languages (ADA, Pascal etc.). Also what is often more important than memory usage is the constant cycle time of the program (since real time system). The another cup of the tea is the electrical layer of the control system, plus the physical layer and all the relations on that layer that can backflash somewhere else in your program if not taken account.

SPI bit banging; MCP3208; Raspberry;error

I am using Raspberry Pi 2 board with raspbian loaded. need to do SPI by bit banging & interface MCP3208.
I have taken code from Github. It is written for MCp3008(10 bit adc).
Only change I made in code is that instead of calling:
adcValue = recvBits(12, clkPin, misoPin)
I called adcValue = recvBits(14, clkPin, misoPin) since have to receive 14 bits of data.
Problem: It keeps on sending random data ranging from 0-10700. Even though data should be max 4095. It means I am not reading data correctly.
I think the problem is that MCP3208 has max freq = 2Mhz, but in code there is no delay between two consecutive data read or write. I think I need to add some delay of 0.5us whenever I need to transition clock since I am operating at 1Mhz.
For a small delay I am currently reading Accurate Delays on the Raspberry Pi
Excerpt:
...when we need accurate short delays in the order of microseconds, it’s
not always the best way, so to combat this, after studying the BCM2835
ARM Peripherals manual and chatting to others, I’ve come up with a
hybrid solution for wiringPi. What I do now is for delays of under
100μS I use the hardware timer (which appears to be otherwise unused),
and poll it in a busy-loop, but for delays of 100μS or more, then I
resort to the standard nanosleep(2) call.
I finally found some py code to simplify reading from the 3208 thanks to RaresPlescan.
https://github.com/RaresPlescan/daisypi/blob/master/sense/mcp3208/adc_3.py
I had a data logger build on the pi, that was using a 3008. The COTS data logger I was trying to replicate had better resolution, so I started looking for a 12 bit and found the 3208. I literally swapped the 3008 out for the 3208 and with this guys code I have achieved better resolution than the COTS data logger.

Fake microphone input for MATLAB

I'm working on a project on MATLAB that records sound and processes. I'm completely fed up of playing the same sounds over and over again during the development.
Is there some kind of way to "fake" the microphone i.e. playing a file on my computer and getting it in MATLAB with the same code I use to record with my mic?
Thanks for any help.
PS: I'm on Mac OS X Yosemite
It depends how you've implemented your code - if you post the relevant sections you'd be able to get more specific suggestions - but in general you might be able to replace the part of the code that captures input from the microphone with a call that reads a file from disk - wavread would be useful for this (http://uk.mathworks.com/help/matlab/ref/wavread.html).
If you're doing realtime stuff then it may or may not work, but if not then you could play the sound file in a third party application and use something to internally rewire the output to the input. Soundflower is one tool that can do this, there are others.
There are more pieces of the puzzle to address.
If just an asynchronous mode of work is possible
If you just wish to work in silence and MATLAB process under development does not require synchronisation with the sound-replay ( not dependent on where the sound-sample starts & just needs "some" sound-related data to be input once the MATLAB code gets ready ), than the easiest way would be to plug a jack-connector into MIC and have the sound re-played in an endless loop by an external device ( MP3 player et al ) and enjoy the silence.
In case a synchronous mode of operations is needed
In case your MATLAB code requires synchronised processing, aligned with the start of the sound-sample and terminating the re-play process once MATLAB code is finished, then you need something a bit more complex than just a re-wired ( be it done physically or virtually ) sound delivery.
There are ways how to allow MATLAB communicate with external processes and thus allow triggering the synchronised events on the remote side ( sending a message alike HeyPythonProcess.startTheSoundREPLAY() ) and make the whole sound-processing both silent ( for example, the python audioservices can move sound-bytes into respective audiomixer paths under your full ( i.e. programmable ) control ) and fully synchronous ( via an event-driven, messaging layer, like ZeroMQ allows )
thus keeping the process as needed.
If this sounds complicated? Yes, it is complicated, but both realistic and possible. MATLAB allows inter-process communications / messaging in a fully autonomous multi-agent manner ( no subordination, indeed a fully autonomous mode of work ) and that gives you an immense power for the future, perhaps, once entering into distributed cloud/grid processing Projects.
Use a side-effect of a bridged mode of MATLAB operations
There is also another synchronous way, to use python-MATLAB bridge, where python side "enforces" synchronicity ( controls the experiment ) and starts / stops the MATLAB part of the work ( thus aligning as a side-effect the replay with the MATLAB processing )
from pymatbridge import Matlab as aMATLAB # get ready
''' #
mlab = aMATLAB() # a class instance ( empty )
'''
mlab = aMATLAB( matlab = '...aMatlabCODE' ) # a class instance ( initialised )
mlab.start() # True once connected.
#
# start playing sound here
# ... and make MATLAB-beyond-the-bridge process it
# ...
# ....>>> |||||||||||||
# vvvvvvvvvvvvv
results = mlab.run_code('a=1;') # process code / vars