Animating with Ruby - ruby

This relates to both physical programming as well as Ruby running on a web server. I have an array of RGB leds, which is 5x5 so a total of 25 leds. They are numbered and individually addressable as such:
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
Here is a photo:
As for the hardware (which really isn't important, because it works fine), the system consists of 25 BlinkM's, an Arduino, and some various cabling and connectors.
The led's are sent commands via serial with a command as such:
#sp.write ["\x01", led, "\x04\x00", "c", color]
Which writes the byte array out to serial using ruby's Serialport gem, the variables "led" and "color" are substituted with the hex of each, so for example if I wanted to make led number 8 turn red, my output would read:
#sp.write ["\x01","\x08", "\x04\x00", "c", "\xff\x00\x00"]
So far all of this works wonders, and I'm really happy with what I have, now my question relates pretty much to general mathematics and simple programming, but somehow the implementation goes over my head.
Here is a sample of such animation. Mostly I'm interesting in how one could animate patterns using ruby here. I recall certain "processing" animation scripts, just looping over a function using the array as an object and affecting the elements of the array creating interesting animations just due to the mathematics of the output.
Does anyone have any idea on how I could get started with something like that? I'm currently able to affect the LED's one at a time with my script, and I can string them together with sleep x after each command and manually build animations, but how could I make one run indefinitely with some sort of procedural animation?
EDIT
I really didn't describe the bytecode array in its entirety, here are what each part does:
#sp.write ["\x01", led, "\x04\x00", "c", color]
^ ^ ^ ^ ^ ^
a b c d e f
a. start byte (not important, tells serial that it is the start of a command)
b. hex for LED address, ex. `\x07` is led 7
c. length of command (starting at "e")
d. bytes to be read (always 0 in our case)
e. the "fade to color" command
f. the color we want to fade to in rrggbb hex format.

It should be easy to map your leds to a 2d array
#led = []
led = 1
5.times do |y|
5.times do |x|
#led[x] ||= []
#led[x][y] = led
led +=1
end
end
I'd probably make an LED class that encapsulates the ability to write out colors, so instead of this:
#led[x][y] = led
it becomes
#led[x][y] = Led.new(:id => led)
And then write a method so you can easily do something like this:
#led[1][5].color(255,255,255)
or whatever.

If you just want to make animations, you should try to abstract away the hardware so it can be represented by some data structure that is easy to work with. I'm not familiar with Ruby so I don't know the best way to go about it. If you were making something like that table, which is just a grid, I would try to map the LEDs to a 2D array.
I would then create an infinite loop. This loop would contain another set of loops that iterates through each pixel in that array and writes the color in each element out to the corresponding hardware. Once it writes out all the pixels, it could then sleep for a few ms, call some function that steps your animation when it wakes and repeat the loop again.
Once you do this then all you'll have to manipulate is that data structure. Does that make any sense?
So something like this:
function stepAnimation(){
//modify 2d array for each step of the animation here
}
//I'm assuming you have a function that gets
//Looped forever. In Wiring you do, not sure
//about working with Arduino using Ruby, if not
//just add while(1) in there..
function mainLoop(){
for(var y = 0; y < 5; y++){
for(var x = 0; x < 5; x++){
sp.write(2darray[x][y]) //write color from array to hardware
}
}
sleep(60);
stepAnimation();
}

Related

ESP32 Deep Sleep Wakeup Though Touchpad

I'm trying to write a program that puts my ESP32 into a deep sleep state, and uses touch input to wake it up. I'm able to put it into the deep sleep state, but as soon as it enters, it wakes up and never calls into the callback function.
Reading the raw data from the touch pad, it idles around 25k, and touch inputs from my hand give it a value of around 180k. The 100k value in the code snippet below is the threshold to where I'm comfortable to determine that a touch has been detected.
I'd like to point out that this is different from ext0 and ext1 wake ups.
static void touchsensor_interrupt_cb(void *arg)
{
... // code here turns on an LED and prints to serial
}
void setup(){
...
touch_pad_init();
touch_pad_config(TOUCH_PAD_NUM2);
touch_pad_sleep_set_threshold(TOUCH_PAD_NUM2, 100000);
touch_pad_isr_register(touchsensor_interrupt_cb, NULL, TOUCH_PAD_INTR_MASK_ACTIVE);
touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_ACTIVE);
touch_pad_sleep_channel_enable(TOUCH_PAD_NUM2, true);
touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER);
touch_pad_fsm_start();
esp_sleep_enable_touchpad_wakeup();
Serial.println("entering deep sleep");
esp_deep_sleep_start();
}
I've triple-checked that my circuit is correct. Running on an ESP32S3 Dev Kit v1.0. If there's a better place to post this please let me know.
The issue ended up being this line:
touch_pad_sleep_set_threshold(TOUCH_PAD_NUM2, 100000);
The threshold here was relative to the raw sensor data. Instead, it should be relative to raw_data - benchmark, where (I'm assuming) the benchmark is computed from what it considers the sensor's baseline value. You can get your benchmark using touch_pad_sleep_channel_read_benchmark.
Printing out the expression above on raw, unfiltered data gives values like:
01:25:10.619 -> 3
01:25:10.696 -> -4
01:25:10.774 -> 3
01:25:10.851 -> -10
01:25:10.930 -> -4
01:25:11.006 -> 20
01:25:11.100 -> -2
01:25:11.177 -> 2
01:25:11.255 -> 1
01:25:11.333 -> 0
Where those values oscillate around 0 (the noise in my touch sensor). I changed the line above it to:
touch_pad_sleep_set_threshold(TOUCH_PAD_NUM2, benchmark * threshold);
Where threshold is 0.2, meaning I'll consider a "touch" when the ESP32 reads sensor values of 120% of the benchmark value. I hope this helps someone.

Divide an image into non-overlapping blocks and applying the 2D DWT on each block

I am working on creating an image splicing detection software so I need to divide the image into non-overlapping blocsk and apply Discrete Meyer Wavelet Transform on each block of the image
I have tried the blockproc function to do that but I got no result:
I = imread('pears.png');
fun = #(block_struct)...
dwt2(block_struct.data,'dmey');
C = blockproc(I,[64 64],fun);
So how can I access the [cA,cH,cV,cD] of dwt2 using the above code?
blockproc assumes that you are outputting an actual image. You cannot use this for multiple outputs. If you truly want this to work with blockproc, you will unfortunately need to call blockproc four times, with each time extracting the different set of coefficients for the directions. Also note that the 2D DWT only works for grayscale images, so you need to convert to grayscale before actually doing any processing. The pears image you've chosen is a colour / RGB image.
I'd like to reference this post on how to select the Nth output given an input function: How do I get the second return value from a function without using temporary variables?. You will need to save this code to a file called nth_output.m, which allows you to programatically extract all output variables from a function and choose only one output.
function value = nth_output(N,fcn,varargin)
[value{1:N}] = fcn(varargin{:});
value = value{N};
end
Simply omitting the extra output arguments when you call the function only gives you the first output, which is what your blockproc code is doing. Once you do that, it's a matter of creating 4 anonymous functions to capture each output from dwt2, and running blockproc 4 times. Make sure you specify which output you want for each of the anonymous functions, so 1 up to 4 and you simply provide a handle to the function you want to run in addition to the input arguments that go into the function.
Therefore, try something like this:
I = rgb2gray(imread('pears.png'));
fun1 = #(block_struct) nth_output(1, #dwt2, block_struct.data,'dmey');
fun2 = #(block_struct) nth_output(2, #dwt2, block_struct.data,'dmey');
fun3 = #(block_struct) nth_output(3, #dwt2, block_struct.data,'dmey');
fun4 = #(block_struct) nth_output(4, #dwt2, block_struct.data,'dmey');
I = rgb2gray(I);
cA = blockproc(I,[64 64],fun1);
cH = blockproc(I,[64 64],fun2);
cV = blockproc(I,[64 64],fun3);
cD = blockproc(I,[64 64],fun4);
cA, cH, cV, and cD contain the DWT coefficients you need for each set of directions.

Terminal dashboard in golang using "termui"

I am working on drawing graphs on the terminal itself from inside a go code.I found this (https://github.com/gizak/termui) in golang. And used this(https://github.com/gizak/termui/blob/master/_example/gauge.go) to draw graph in my code.
Problem is this , as we can see in the code( https://github.com/gizak/termui/blob/master/_example/gauge.go ), they are passing g0,g1,g2,g3 all together in the end "termui.Render(g0, g1, g2, g3, g4)".
In my case I don't know how many gauges to draw before hand so I used a list to store gauge objects and then tried to pass list to render.
termui.Render(chartList...)
But it creates only one gauge.
This is how I am appending elements in the list.
for i := 0; i < 5; i++ {
g0 := termui.NewGauge()
g0.Percent = i
g0.Width = 50
g0.Height = 3
g0.BorderLabel = "Slim Gauge"
chartList = append(chartList, g0)
}
what I am getting is a gauge for i=4 only. when I am doing termui.Render(chartList...)
Am I doing something wrong?
PS - I have modified question based on the answer I got in this question.
Here is a good read on Variadic Functions
Take a look at the function signature of Render, https://github.com/gizak/termui/blob/master/render.go#L161
func Render(bs ...Bufferer) {
All you need to do is
termui.Render(chatList...)
assuming chartList is a []Bufferer
Edit
You are only seeing one because they are stacking on top of one-another. To see this add
g0.Height = 3
g0.Y = i * g0.Height // <-- add this line
g0.BorderLabel = "Slim Gauge"
From a quick review of the project, it appears there are ways for auto-arranging that have to do with creating rows (and probably columns). So you might want to explore that, or you will need to manually position your elements.

How can I learn the starting time of each frame in a video?

It is very critical to learn the start time of each frame of a video.
I need to determine the starting point manually ( for example 848 here) by using below matlab code:
v = VideoReader('video1.avi','CurrentTime',848);
while hasFrame(v)
video_frame = readFrame(v);
counter=counter+1;
if counter==1
imshow(video_frame)
imhist(video_frame(:,:,1))
end
end
What I want is to distinguish some video frame from the others by using histogram. At the end my aim is to reach the exact showing time of the distinguished frames.
After editting:
This is frame histogram outputs:
Histogram size of the some frames are different from the previous one, do you know the reason?
difference=[difference sum(abs(histcounts(video_frame)-histcounts(lastframe)))];
Because of the taking the difference of the I had remove the different histogram sized frames but it causes missing some frames.
i havent found an video example that looks like what you discribe. please condsider always to have an example.
This example code calculates the differences in the histcounts. please notice that waitforbuttonpressis in the loop so you have to click for each frame while testing or remove it when the video is too long. Does this works on your file?
v = VideoReader('sample.avi','CurrentTime',1);
figure1=figure('unit','normalized','Position',[0.2 0.2 0.4 0.6]);
axes1=subplot(3,1,1);
axes2=subplot(3,1,2);
axes3 = subplot(3,1,3);
counter=0;
difference=[];
video_frame=readFrame(v);
while hasFrame(v)
lastframe=video_frame;
video_frame = readFrame(v);
counter=counter+1;
imshow(video_frame,'Parent',axes1);
[a,b]=histcounts(video_frame(:,:,1));
plot(b(1:end-1),a,'Parent',axes2);
difference=[difference sum(abs(histcounts(video_frame,0:255)-histcounts(lastframe,0:255)))];
bar(1:counter,difference,'Parent',axes3);
waitforbuttonpress
end
[~,onedistinguished]=max(difference);
%defining a threshold like every value that is bigger 4000
multidistinguished=find(difference>4000);
disp(['majorly changed at: ' num2str(distinguished)]);

Arduino keypad matrix example? ( teensyduino )

I'm a beginner using Arduino with a Teensy 3.2 board and programming it as a usb keyboard.
I have two 4 button membrane switches. Their button contacts are on pins 1-8, and the 9th pin holds a soldered together wire of both membrane switches' "ground" line or whatever it's true name is; the line that completes the circuit.
Basically when you press the buttons they are supposed to simply type "a, b, c..." respectively. I've been told I need to use a matrix for this.
I'm looking for an example of how to code a keyboard matrix that effectively supports a one row/9 column line (or vice versa?) I've been unable to find that solution online.
All I have so far is this code which, when the button on the second pin is pressed, sends tons of "AAAAAAAAAAAAAAAA" keystrokes.
void setup() {
// make pin 2 an input and turn on the
// pullup resistor so it goes high unless
// connected to ground:
pinMode(2, INPUT_PULLUP);
Keyboard.begin();
}
void loop() {
//if the button is pressed
if(digitalRead(2)==LOW){
//Send an ASCII 'A',
Keyboard.write(65);
}
}
Would anyone be able to help?
First of all, a 1-row keypad is NOT a matrix. Or better, technically it can be considered a matrix but... A matrix keypad is something like this:
You see? In order to scan this you have to
Pull Row1 to ground, while leaving rows 2-4 floating
Read the values of Col1-4. These are the values of switches 1-4
Pull Row2 to ground, while leaving rows 1 and 3-4 floating
Read the values of Col1-4. These are the values of switches 5-8
And so on, for all the rows
As for the other problem, you are printing an A when the button is held low. What you want to achieve is to print A only on the falling edge of the pin (ideally once per pressure), so
char currValue = digitalRead(2);
if((currValue==LOW) && (oldValue==HIGH))
{
//Send an ASCII 'A',
Keyboard.write(65);
}
oldValue = currValue;
Of course you need to declare oldValue outside the loop function and initialize it to HIGH in the main.
With this code you won't receive tons of 'A's, but however you will see something like 5-10 'A's every time you press the button. Why? Because of the bouncing of the button. That's what debouncing techniques are for!
I suggest you to look at the class Bounce2 to get an easy to use class for your button. IF you prefer some code, I wrote this small code for another question:
#define CHECK_EVERY_MS 20
#define MIN_STABLE_VALS 5
unsigned long previousMillis;
char stableVals;
char buttonPressed;
...
void loop() {
if ((millis() - previousMillis) > CHECK_EVERY_MS)
{
previousMillis += CHECK_EVERY_MS;
if (digitalRead(2) != buttonPressed)
{
stableVals++;
if (stableVals >= MIN_STABLE_VALS)
{
buttonPressed = !buttonPressed;
stableVals = 0;
if (buttonPressed)
{
//Send an ASCII 'A',
Keyboard.write(65);
}
}
}
else
stableVals = 0;
}
}
In this case there is no need to check for the previous value, since the function already has a point reached only when the state changes.
If you have to use this for more buttons, however, you will have to duplicate the whole code (and also to use more stableVals variables). That's why I suggsted you to use the Bounce2 class (it does something like this but, since it is all wrapped inside a class, you won't need to bother about variables).

Resources