Traditionally, robot arms have been controlled either by joysticks, buttons, or very carefully programmed routines. However, for [Narongporn Laosrisin’s] homebrew build, they decided to go with gesture control instead.
The MeArm robotic arm is built using laser cut acrylic parts, and can be had in a kit if so desired. It features four servo motors, charged with rotating the arm’s base, pushing the arm forwards and backwards, up and down, and actuating its gripper. The servos are under the command of a micro:bit microcontroller board, which itself receives signals from a second micro:bit which is strapped to the human wishing to control the arm. The second micro:bit detects gestures with its accelerometer, and then sends the relevant commands to the robotic arm’s micro:bit over its built-in radio link. The arm controller then commands the servos to execute the maneuver.
It may be a small robotic arm that doesn’t have the capacity to lift much, but that’s not the point. This project is a great way to teach students how to program microcontrollers, work with sensor inputs, and just generally how to solve engineering puzzles. To that end, it looks like [Narongporn] has a great project on hand for teaching their students. Video after the break.
Chromium(III) Telluride (Cr2Te3) is an interesting material for (ferro)magnetic applications, with Yao Wen and colleagues reporting in a 2020 Nano Letters paper that they confirmed it to show spontaneous magnetization at a thickness of less than fifty nanometers, at room temperature. Such a 2D ferromagnet could be very useful for spintronics and other applications. The confirmation of magnetization is performed using a variety of methods, including measuring the Hall Effect (HE) and the Anomalous Hall Effect (AHE), the latter of which is directly dependent on the magnetization of the material, rather than an externally applied field.
More recently, in a June 2023 article by Hang Chi and colleagues in Nature Communications, it is described how such epitaxially obtained Cr2Te3 films show a distinct change in the AHE (in the form of sign reversal) depending on the strain induced by the interface with the various types of substrates (Al2O3, SrTiO3) and the temperature, likely owing to the different thermal expansion rates of the film and substrate. Underlying this change in the observed AHE is the Berry phase and the related curvature. This is a phenomenon that was also noted by Quentin Guillet and colleagues in their 2023 article in Physical Review Materials, effectively independently confirming the AHE
Using Cr2Te3 in combination with the appropriate substrate might ultimately lead to spintronics-based memory and other devices, even if such applications will still take considerable R&D.
Top image: Crystal structure of Cr2Te3 thin films. (Credit: Hang Chi et al. 2023)
With the increase in popularity of Internet of Things (IoT) devices and their need to communicate wirelessly, there’s been a corresponding explosion of wireless protocols to chose from. Of course there’s Wi-Fi and Bluetooth, but for more specialized applications there are some other options like Z-Wave, LoRa, Sigfox, and Thread. There’s a decent amount of overlap in their capabilities too, so when [SHS] was investigating some low-cost Xiaomi sensors it was discovered that it is possible to convert them from their general purpose Bluetooth protocol over to the more IoT-specialized Zigbee protocol instead.
These combination temperature and humidity sensors have already been explored by [Aaron Christophel] who found that it’s possible to flash these devices with custom firmware. With that background, converting them from Bluetooth to Zigbee is not a huge leap. All that’s needed is the Zigbee firmware from [Ivan Belokobylskiy] aka [devbis] and to follow the steps put together by [SHS] which include a process for flashing the firmware using an over-the-air update and another using UART if the wireless updates go awry. Then it’s just a short process to pair the new Zigbee device to the network and the sensor is back up and running.
Converting from one wireless protocol to another might not seem that necessary, but using Bluetooth as an IoT network often requires proxy nodes as support devices, whereas Zigbee can communicate directly from the sensor to a hub like Home Assistant. Other Zigbee devices themselves can also act as a mesh network of sorts without needing proxy nodes. The only downside of this upgrade is that once the Bluetooth firmware has been replaced, the devices no longer has any Bluetooth functionality.
Once upon a time, if you wanted to generate some waveforms, you needed to buy an expensive off-the-shelf function generator or whip up a big pile of analog electronics. Not so today, when you can grab a fast microcontroller off the shelf and have it squirt out whatever fancy waves you might desire. That’s just what [rgco] did to build this nifty arbitrary wave generator.
The build improves on prior work by [rgco] with the Arduino Uno, with which they built a device that could output at 381 kilosamples per second, with each sample update taking 42 instruction cycles. Thanks to the Pi Pico’s faster clock speed and certain performance optimizations, they were able to up that to a mighty 125 megasamples per second, using the DMA and PIO subsystems to output a new sample every single clock cycle.
The result is a cheap function generator you can build with a Pi Pico and a handful of resistors, which will probably cost you the grand total of $12. It readily outperforms, at least in regards of speed, devices based on the AD9833 function generator chip, which only runs at 25 megasamples. Plus, that chip can only output sines, triangles, and squares!
Even a passable function generator can be a useful tool to have in the workshop, as we’ve seen before. Video after the break.
On the surface, the electric grid might seem like a solved piece of infrastructure. But there’s actually been a large amount of computerized modernization going in the background for the past decade or so. At a large scale this means automatic control of the grid, but for some electric utility customers like [Alex] this means the rates for electricity can change every hour based on demand. By keeping an eye on the current rate, you can extract the most value from these utilities.
[Alex] is located in the United Kingdom and has an energy provider whose rates can change every half hour. This information is freely available well enough in advance to download the data and display it visibly in with a NeoPixel LED ring around a clock. The colors displayed by the LEDs represent an increase or decrease in price for the corresponding time and allow him to better plan out the household’s energy use for the day. The clock uses a TinyPICO ESP32 module to gather the data and handle the clock display. A second wall-mounted device shows real-time energy readings for both gas and electricity using two old analog voltmeters modified to display kilowatt-hours.
While not everyone has a utility which allows this sort of granularity with energy pricing, having one can make a bit of a difference as electricity rates under this system can sometimes go negative. [Alex] estimates that using these two displays to coordinate his energy usage has saved around £50 a month. Even if your utility offers minimal or no price adjustments for time-of-use, it’s still a good idea to monitor energy use in your home. Here’s a fairly comprehensive project that does that without modifying any existing wiring.
Last time, I assembled a Python object representing a Rigol oscilloscope. Manipulating the object communicates with the scope over the network. But my original goal was to build a little GUI window to sit next to the scope’s web interface. Had I stuck with C++ or even C, I would probably have just defaulted to Qt or maybe FLTK. I’ve used WxWidgets, too, and other than how many “extra” things you want, these are all easy enough to use. However, I had written the code in Python, so I had to make a choice.
Granted, many of these toolkits have Python bindings — PyQt, PySide, and wxPython come to mind. However, the defacto GUI framework for Python is Tkinter, a wrapper around Tk that is relatively simple to use. So, I elected to go with that. I did consider PySimpleGUI, which is, as the name implies, simple. It is attractive because it wraps tkinter, Qt, WxPython, or Remi (another toolkit), so you don’t have to pick one immediately. However, I decided to stay conservative and stuck with Tkinter. PySimpleGUI does have a very sophisticated GUI designer, though.
About Tkinter
The Tkinter toolkit lets you create widgets (like buttons, for example) and give them a parent, such as a window or a frame. There is a top-level window that you’ll probably start with. Once you create a widget, you make it appear in the parent widget using one of three layout methods:
Absolute or relative coordinates in the container
“Pack” to the top, bottom, left, or right of the container
Row and column coordinates, treating the container like a grid
The main window is available from the Tk() method:
That’s about the simplest example. Make a button and close the program when you push it. The mainloop call handles the event loop common in GUI programs.
Newer Widgets
Some tkinter widgets look old-fashioned, but newer variants can automatically replace the old ones. The new widgets are packaged as tkinter.ttk. These new widgets have slight differences, but most of the basic setup remains the same. The appearance functions are different, though. For example, a normal button uses fg and bg to set the foreground and background colors. A ttk button uses a style system that is more complex to set up, but also more powerful.
It is dead simple to use the new widgets. Normally, you’d import the whole GUI library with an import. You can import ttk from the tkinter module and then refer to the widgets explicitly (e.g., ttk.Button). However, it is common to simply import everything from tkinter and then use tkinter.ttk to override anything that is in the ttk library. For example:
from tkinter import *
from tkinter.ttk import *
Now, every reference to Button, for example, will resolve to ttk.Button. There are 18 “new” widgets, including some that don’t appear in the original tkinter, like Combobox and Treeview.
GUI Builder?
I started out looking for a good GUI builder for tkinter and I didn’t really find much. There’s a website that doesn’t seem to work well (and doesn’t handle ttk), a project that uses a paid GUI builder and then translates its output to tkinter, and PAGE.
PAGE is actually not bad but a little quirky. What I didn’t like was that it does the ordinary placement layout, which means a form you design might look bad on some machines due to font sizes or other factors. So a button might be placed at, say, 0.034 x 0.267 from the top corner of its container. In other words, 3.4% across and 26.7% down. However, if you spend some time with it, it does work and probably generates code that looks ok more than it fails to render nicely.
However, I finally decided just to build the GUI manually. It isn’t that hard. If you want a simple experience, check out PySimpleGUI I mentioned earlier. The layout there is a list of lists. Each list is a row in the GUI. That’s it. So: [ [ Row_1_column_1, Row_1, column_2,...],[Row_2_column_1,....],...]. That’s very simple to deal with. But doing it directly in tkinter is not bad, either.
Layout
I used a simple class to lay out my GUI and tried to keep it agnostic to the scope more or less. It creates a Scope object (from the last post) and manipulates it, but it doesn’t understand the commands or the communications. If you are a traditional GUI programmer, the scope object is the model and the GUI class is the view and the controller.
Most of the work occurs in the class constructor. There are three main parts:
Some internal state variables like connected and the scope object, which, initially is None.
The creation of GUI widgets. This doesn’t show anything; it simply creates the objects. This section also creates some ttk styles for use with the Run/Stop button.
The final section arranges the widgets in their parents.
You have to get used to the idea that you specify the parent widget in step 2, but you set the widget’s position in step 3. For example, consider this excerpt from the code:
self.clabel=LabelFrame(self.top,text='Control')
self.rsbtn=Button(self.clabel,text="Run/Stop",command=self.do_rs,style="GoBtn.TButton")
. . . # create more stuff
self.rsbtn.pack(side="left")
. . . # more buttons here
self.clabel.pack(side='top',fill='both',expand='yes')
Here’s what that part of the layout looks like on the screen.
The first line creates a labeled frame attached to the top window. Then, the code makes a button that is a child of the label. It has some text, a style, and a function to call when you push the button.
Placing the button is easy. Then, the label itself has to be packed into the main window. In this case, it goes to the top and will fill the available space. It will also expand if you resize the window.
In the main class, I only use the pack layout manager. However, I also use the grid manager in a custom component. A tiny bit of code at the end of the constructor captures the Enter key so you can type in an IP address and hit Enter instead of pressing the connect button. The code also sets the focus on the entry field. If you are a keyboard aficionado, the tab order, by default, is the order you create the widgets, although you can change that in the software.
If you are looking for a full tutorial on tkinter, plenty are around. TutorialPoint has one that is a fast read.
Custom Components
The direction pad is a custom tkinter component
For the scope controller, I needed some direction pads. That is, four arrow buttons going in different directions and a center button you can push. The tkinter library has nothing like that, but that’s not a problem. You can simply build it yourself. The tkinter widgets are just classes, and you can easily extend them to make your own variations and composite widgets.
First, I needed a small button, and out of laziness, I decided to create a custom component. I simply derived a new class from Button and set a default width of 1 in the constructor. Truthfully, I should have just hardcoded the width. If you are going to supply a width, why not just use a regular button? Anyway, here’s the entire code:
# Create a tiny button
from tkinter import *
from tkinter.ttk import *
class Button1(Button):
def __init__(self, parent,text='',command=None,width=1):
Button.__init__(self,parent,text=text,command=command,width=width)
As you can see, creating a custom widget doesn’t have to be a big deal. Normally a good base class for custom widgets is Frame. A frame can hold other widgets; by default, it is invisible. Just what you need. In this case, though, it made more sense to customize the Button class.
I did use Frame as the base class for the direction pad. I create some buttons that use a lambda — an anonymous, inline function — for their actions. This lets the code easily call a single callback for all the buttons. The default callback breaks everything back out to functions like up or down.
At first, that might seem crazy. Why not just assign the function directly to the key? The answer is reusability. There are several ways to use the custom component:
Set a non-default callback. This is a single function to process all keys.
Create a new subclass and replace the default callback. Again, this is a single function for all keys.
Create a new subclass and replace each of the low-level functions. This provides separate functions for each key.
The layout is simple, using the grid call to set a row and column:
Now, the main code can create two different direction pads without problems.
The Whole Enchilada
You can find the entire code on GitHub. Once you get past the GUI layout, most of the code just calls the object from the last time that actually talks to the scope.
There are two interesting things, though. Since the DHO900 doesn’t give you a way to emulate key presses, the program has to understand a bit about the state of the device. For example, pressing the Run/Stop button works differently if the scope is already running or already stopped. So, the program needs to know the current state to send the right command.
It is possible to query the scope at the time of the command, of course. However, I wanted the program to track the state periodically and update certain UI elements. For example, I wanted the Run/Stop button to show red or green based on what would happen if you pressed the button. The trigger type combo box, too, should reflect the current trigger state even if someone manually changes it.
Luckily, tkinter provides a way to add delay processing to the event loop using after. The code calls it against the top window with a delay in milliseconds. When the timeout expires, the tick function runs. To keep the timer function going, tick must also rearm itself by calling after again. Before that, though, the code queries the state of the scope and updates the UI along with some state variables in the UI object.
The program seems to work well and should be much easier to port to a different scope now. If you can’t tell, GUIs are generally not my thing, although I build them when I have to. For simple stuff, tkinter isn’t half bad.
Once you can control your scope and grab data from it, there are lots of fun things you can do. Things can quickly get out of hand — but in a good way.
As you might expect, Apple’s AirPods are a fine example of miniaturization. They’re packed to the gills with hardware, with very little wasted space inside. Flexible PCBs hook up the electronics in an elegant and tidy fashion. Three tiny MEMS microphones are on board to capture the user’s voice and filter out noise. The battery that runs the show is a hefty lithium-ion coin cell which fills almost all the empty space behind the audio driver.
By contrast, the fakes look positively weedy inside. They cut out the bonus microphones, using just one to do the job. Wires link up the different components, with unimpressive blobby soldering visible that has splattered around the internal enclosure. Even the cases are lower-tech, with a weaker battery and a poorer charging solution. Hilariously, cheaping out on the tech makes the fakes lighter, so they compensate by adding weights to create a sense of heft for the user.
It’s amazing how much is revealed by a CT scan, that doesn’t even require opening the devices to tear them down. Fake hardware really is a scourge that many in the tech industry find themselves fighting against on a regular basis.