Handmade Powerful 100W flashlight

I had an old LED COB light that the power conversion circuit failed, so I decide to gut it and turn it into a lantern / flashlight with a spare 6V sealed acid battery, using a simple DC-DC (boost) converter board.

The 6V lead acid battery eventually died so I converted the unit to accept 6V~12V from outside. The whole lanter was made from whatever leftovers/excess materials I have in my lab, including a PC fan I got for free after rebates years ago. The case is made out of the case for a roll of lint-free alcohol wipes.

 2 total views

Foobar2000 alternatives for Linux

I am a big fan of foobar2000 because it’s one of the most terse yet flexible package for playing music. I tried using RhythmBox that came with Linux Mint, but it’s annoying as hell. When you double click an audio file, it’ll adds to a default playlist and after it finished playing, it’ll go and play other songs you’ve previously clicked (because they were accumulated on the playlist).

Out of frustration, I tried to stick with my favorite, I found foobar2000 has a wine port available on Snap package manager. Downloaded it and realized it has a lot of work to do to make it work on linux:

  • Fonts do not scale. It’s always that tiny and not all the UI controls looks odd
  • The paths assumed windows drive letters. Sometimes if I drag and drop files from a bitlocker drive (mounted with dislocker), it’ll assume the file came from some complicated path under Z:\. WTF

Ended up downloading Clementine. It at least let me remove songs from the playlist by pressing “Del” button. But I’m not happy that it doesn’t have CDDB.

Turns out there are better options the Clementine. I found this StackExchange while searching for FreeDB options:

https://askubuntu.com/questions/541977/a-music-player-with-cd-ripping-and-cddb-lookup

Turns out DeaDBeeF (a hex pun) looks like a watered down version of foobar2000. So, Clementine, Foobar2000-Wine and RhythmBox is out.

 113 total views,  3 views today

Advanced classical Taiwanese swears 100年前台灣人都罵什麼髒話?絕對不只「X你娘」,一口氣譙完

https://www.storm.mg/lifestyle/225114

相較於源遠流長直接幹到開台第一代祖先的「幹你開基祖」,「幹你娘」還真的遜色很多,而當年清代漢人移民台灣產生的種種髒話,更是精采。因為泉州人看漳州人不爽,所以有了「幹你大聖王」(大聖王指開漳聖王)這句,直接幹上神明,了不起(放在今日,大概就像你看基督徒不爽,而怒罵「幹你耶和華」)。

由於當年醫療衛生環境不佳、死亡率高,詛咒別人去死,也成了慣用的侮辱手法,威力驚人。例如「死無半個點香點蠋(無人送終)」、「汝著死的十字路頭被狗哺(橫死十字路口頭還被狗咬)」、「拾骨頭尋無墓(後人撿骨找不到墓)」,句句都是要人命。

 65 total views

FREE oscilloscopes for innovators in response to #CCPvirus

https://www.humgar.com/CCPvirus-Urgent-Innovation-Response/

In the time of national emergency against the Chinese Communist Party Virus, or #CCPvirus in short, we are glad to offer FREE basic 100Mhz oscilloscopes (or mixed-signal oscilloscopes) to makers and engineers in the US who are stepping up with innovations to help.

Example include:

  • Simple ventilators that can be built quickly within US (https://www.agorize.com/en/challenges/code-life-challenge)
  • Robots that reduce direct human interaction with the infected patients
  • Machines that sanitize the contaminated environment quickly and efficiently
  • Any innovation you can come up with to help the front-line medical staff, produce the medical supplies we need, improve the logistics, and means to slow the spread.

Just send me (to wonghoi@humgar.com)

  • a project description
  • why you need the oscilloscope
  • whether you need the logic analyzer function (mixed-signal)
  • does your project require fancy oscilloscope features like FFT, calculus, phase difference, deep memory, talking to the PC
  • your name, address and phone number for shipping

and I’ll make the arrangements immediately.

Currently available models (subject to availability)

  • HP 54645A
  • HP 54645D
  • Agilent 54622D (Mixed-Signal)
  • HP 6632B Systems Power Supply (20V, 5A, Fast recovery)

These models has a no-brainer learning curve for any motivated maker/engineer who are up to the game innovating something serious. Time is ticking. We want you to use the oscilloscope right away! Higher bandwidth oscilloscopes are available as loaner if your project justifies it.

It’s on an honor system. Please don’t abuse the program so the innovators who genuinely need the oscilloscope will have what they need!

We thank all the innovators who contribute their time and effort in response to the CCP virus outbreak!

Stay safe, wash your hands, and stay home whenever practical.
Save lifes by slowing the spread within our medical system’s capacity.

 117 total views

Shortest Explanation to NAND SR-flip-flop

When I was in high school studying electronics on my own as a hobby (it was not taught in the curriculum. No, physics people culturally hates electronics, they consider it a chore.), I followed the logic states of the bistable (two NAND gates) meticulously. However, it was tedious and hard to remember correctly.

There’s a fast way to reconstruct the explanation from scratch. You’ll need these invariants:

  • ‘1’ is ‘let the other input decide’ in AND logic (1 & A = A)
  • ‘0’ is ‘action‘ in AND logic, namely clear (0 & A = 0)
  • NAND is practically a NOT gate if you tie the inputs together
  • Two NOT gates chasing each other generates Q’ and Q
  • NAND gates provides a mean for external inputs to disturb the chasing NOT gates

By leaving external inputs (S and R) at ‘1’, we are letting the state pins decide, behaving like the two chasing NOT gates.

The only way to disturb the state is to create a ‘0’ (clear) action. The circuit is symmetric, so ‘S’ and ‘R’ is arbitrary as long as you are willing to switch the roles of Q and Q’.

  • Set Q to ‘0’ by sending a ‘0’ (clear action) through ‘S’
  • Set Q’ to ‘0’ by sending a ‘0’ (clear action) through ‘R’

There are no other valid actions in this configuration.


Side note: persisting the clear action will lead to 0 & 0 = 0 at the applied input and 1 & 1 = 1 at opposite NAND gate, which the achieved state remains. Normally we want to return the external inputs back to 1 to receive future commands (actions) correctly, both external inputs asserting low is invalid.

It’s more natural to have S and R being active high in transistor’s implementation. NAND’s ‘S’ and ‘R’ are active low (so technically, I should use S’ and R’ instead, but I’m following the more common nomenclature for the moment for the NAND gate implementation).

 102 total views

Stanford SRS PS350 High Voltage Power Supply Repair

I received two PS350 power supply units that one of it has sparks when output is enabled and the other just won’t output anything at all.

The only repair info I found is from one of my favorite youtube channel the Signal Path. However, his unit has a much easier problem: the solder joints cracked because PS350 uses the metal case as a shield that are subjected to mechanical stress.

However, after difficult troubleshooting, I realized one unit has a fried resistor in the HV section, and a few core MOSFETs shorted.

The other unit is much more difficult: not only the HV capacitor is blown, resistor is blown, diodes shorted (won’t be able to detect it by probing in-circuit because of the capacitor ladder), PCB trace to the feedback path vaporized (without that the voltage will rise uncontrollably until something’s fried), and a bunch of MOSFETs, transistors and regulators ICs needs to be replaced.

Likely both units are broken because the users switched polarity without turning the HV section off (and let the voltage bleed out). This is very important and the markings on the case already warned the user NOT to do so.

You absolutely must NOT change the polarity while the output is live because the components in the HV section are marked for 4~6kV, so there is little room for a voltage spike past the operating voltages. The act of switching out the polarity (by mechanically swapping the pins through the dial switch at the back) doubles the voltage stored in the capacitors in a voltage multiplier ladder, so you are almost sure to crack the HV capacitors and likely the HV diodes.

Since I’ve developed experience for repairing SRS PS350, since I had to reverse engineer some of the circuit sections, I welcome request for repair evaluation (no fix, no fee). Please call me at 949-682-8145, or meet me at www.humgar.com.

 188 total views

Modifying mutable (like bytearray) arguments’ data in Python functions Use slice assignment x[:] = ... to replace the entire contents. Dynamically typed language lets you shadow input arguments with a local variable!

I’d like to write a function to selectively modify lines read from a file handle and write it back. By default, lines are read as byte()  objects that are immutable, so I converted it to bytearray() instead so it can be modified because only a few lines meeting certain criteria needs to be changed.

When I try to refactor similar operation into a function, I was hoping to pass the mutable bytearray() as an argument and directly modify the caller’s content like in C++, given Python variables works LIKE reference binding.

I know bytearray.replace() does not modify the data in place, but instead outputs the modified line to a new variable. Normally, I can simply do this:

line = line.replace(b'\tCLASS', b'')

and the code will work. However, it doesn’t do anything when I try to pass it as an argument to a Python function (unless I return line as output). Although I am well aware that Python variables assignments to existing variables means orphaning the old data and re-purposing the label, the variable assignment behavior in Python requires careful thought when used in non-idiomatic situation.

In other words, I want this function to have side effects on the variable ‘line‘, but I wasn’t doing it right. This is a tempting mistake for people with a C/C++ background: in C/C++, it is not possible to shadow an input parameter even if we were to explicitly declare it, so the innocent assignment I did above has to modify the object in the caller (passed as a reference to the function) in C/C++, as if I did this directly in the caller.

However, in Python, variables do not need to be declared (aka, dynamically typed). This opens up the possibility of unwittingly shadowing the input parameters, which is what happened here. Mutable arguments on the stack still can be modified through the function, but when you assign a variable using ‘=’ operator, a new local variable with the name on the LHS is created, which shadows the input parameter.

This means the connection to the caller objects is lost during shadowing.

The correct way to do this is use slice assignment (which the logic/concept is very different despite the syntax is similar) to replace all the contents of the input variable with the output of bytearray.replace():

def remove_from_header_token_CLASS(tokens, line):
     # line is expected to be byte array (mutable)    
    try:
        column_CLASS = tokens.index(b'CLASS')
    except:
        column_CLASS = None
    else:
        line[:] = line.replace(b'\tCLASS', b'')  
                
    return column_CLASS

Since Python has a clear distinct concept of parameter variable (from local variable), trying to apply nonlocal keyword over it (in hopes to broaden the scope) will not parse/compile.


This is actually the same behavior as in MATLAB (dynamic typing) for the same reason that variables does not have to be declared like in C/C++ (static typing). In MATLAB, if you choose to have a handle object (which works like references), you can shadow the input argument by creating a local variable of the same name:

classdef DemoHandleClass < handle
    properties
        x = 3;
    end
end

function demo_shadowing()
    C = DemoHandleClass();
    f(C);
    
    disp(C.x)
end

function f(C)
    C = DemoHandleClass();  // Shadowing
    C.x = 14;
end

The above MATLAB program will display 14 without shadowing and 3 with shadowing (C became a new local variable that has nothing to do with the input argument C). MATLAB users rarely run into this because the language design heavily discourage side-effects: we are supposed to return the changed local variable to the caller. The only way to do side-effects in MATLAB is through handles (which you need to establish a class, which is clumsy). Technically you can write the data to external resources (e.g. file) and read it back. But guess what? Resources are accessed through handles, so there’s no escape.


Of course, there’s a better way to do so (MATLAB’s preferred way): return the modified object back to the caller as if they are immutable:

def remove_from_header_token_CLASS(tokens, line):
     # line DOES NOT HAVE TO BE MUTABLE    
    try:
        column_CLASS = tokens.index(b'CLASS')
    except:
        column_CLASS = None
    else:
        line = line.replace(b'\tCLASS', b'')  
                
    return column_CLASS, line

This is what I ultimately used (so I ended up not converting the byte lines to bytearray), given that Python’s tuple syntax make it easy to return multiple outputs like MATLAB. The call ended up looking like this:

column_SPL_CLASS, line = remove_from_header_token_CLASS(tokens, line)                

Nonetheless, I think there’s an important lesson to be learned for doing side-effects in dynamically typed languages. Maybe I’ll need this one day if I get an excuse to do something more complicated that genuinely requires side-effects.


In summary, variable assignments in most dynamically typed languages will shadow the input argument with a newly generated local variable instead of modifying the data in the original input argument. This implies that there function side-effects cannot be carried out through variable assignment.

The most common implication is: do not (equality) assign to a input variable to modify its contents in a dynamically typed language.

 230 total views