20 de enero de 2015

A late christmas tree with LEDs

For this new year season, I and  my daughter made a christmas tree lit with LEDs. It's about 5 cm (3 inches) high. We finished it late, aproximately at January 10.

To fit the entire circuit inside the tree, we put a watch battery with the battery, a latching switch, several small red LEDs (3mm) and a normal yellow LED (5mm). It doesn't blink, you have to turn it on and off by hand. For the tree structure, we used the so called cold porcelain (autotranlation) mixed with dyes. (I only drew four red LEDs in the circuits to keep them simple.)


Circuit diagram

The battery holder and the smallest switch we got were designed to use in a breadboard or printed circuit. They were much smaller than the other versions we found, but it was difficult to solder them.

We cut the LEDs terminals that are made of hard wire and replace them with insulated thin wires, so that we can be arrange them at the correct position. The original terminals have different lengths to distinguish the anode from the cathode. When you cut them this distinction is lost, so we resorted to the old trick to connect the LED at the two possible positions. (Actually the shape of the inner parts of the LED also serves as a guide, but I trust more what the battery says.)

Circuit without tree

To get an idea of the length of the wires, the positions, and how we were going to place the components in the tree, I drawled it on paper and settle the components (the artistic conception is mine).

Circuit over tree blueprint

After a few tries to arrange the components, we put the switch in the trunk of the tree and the battery in the bottom so it can be replaced. The other option was to make a pot to hide the battery and switch, but the pot was too big.

The battery can be replaced at the bottom

The switch is in the trunk

The problem is that I am a Chemical Technician (at the secondary school) (I dissolve circuits, I don't built them :)) and it was the first time my daughter tried to solder. Moreover the components were designed to use in a breadboard or printed circuit, not to be soldered. So we had to remake several times each solder joint until all of them were good. In general the easiest method was to make a small loop at the tip of wire, adjust it to the terminal with pliers and then solder. After all this steps, one of the LEDs died, so the tree got only five red LEDs and a yellow one.

We keep moving the circuit to verify that all the solder joints are good and strong. For example one of the solder joints of the switch was loose and then the tree turned off or twinkle (it twinkle!) spontaneously. Luckily, we realized this when only we had made the base and the trunk, so we have just to break the first version of the trunk, resolder and remade the trunk.

Circuit with base and trunk

Most of the circuit was isolated but close to the terminals of the LEDs they have some uninsolated parts. Luckily the cold porcelain is an insulator (at least at 5V), so we only have to be careful to put some cold porcelain (of the correct color) between the terminals of LED and around some other points that had no insulation.

For the tree structure we made a light green base that looks like grass and dark brown trunk. Then we put a very dark brown cone, that has almost the final form of the tree. (I wanted to make the tree wider like in the artistic conception, but my daughter insisted with a more elongated shape.) After that we put some green flat "leaves" (in the form of droplets) and press them to make them stick. We also put some colored beads. At each step we were turning the tree on and off to besure we have not broken any part of the circuit.

Finished tree (off)

Finished tree (on)

Using the GIMP magic we get

Fake photo of twinkling tree :)

Comments and future projects

The cold porcelain worked fine. We could handle it for long time adding a drops of water. In case of errors it can be removed, without leaving all the components completely stained. After a day it's firm but slightly flexible, with one or two more days it hardens completely.

Cold porcelain is also an insulation (at least at 5V), so it was useful to enclose the circuit without problems. There is a very small distance between the terminals of the LEDs and we have also the solder joints and the tips of the wires that are uninsulated, so with the movement any of them can be short-circuited. (With a 5V battery it's not a problems.)

One of the LEDs died before we put the tree. I don't know whether it was caused by moving the terminals too much for soldering or we heated the LED too much while soldering or ...

One of the LEDs has a bad solder, so you have to give it a technical tap from time to time to fix it.

The battery holder is brittle and the cold porcelain got inside by the borders. I don't know if it will be easy to replace the battery, I hope it lasts several years ...

It doesn't twinkle! Let's see if we make one tree with a 555 next year, but before that I should find out how to connect a 555 (I can dissolve a 555!). It will be complicated because there are more components to solder.

As an electronics expert should have noticed, we did not put any resistors (I take full blame). The idea was to minimize the amount of solder joint to make the project easier. Moreover, all the solder joints of the resistors would have no insulator, so we should be more careful to isolate them with tape or cold porcelain.

The biggest practical problem is due that there are two LEDs colors. The photon of yellow light have more energy than the photons of red light, so the yellow LED needs more voltage than red, approximately 2.0V vs. 1.7V (in practice everything is a bit more complicated). Then the red LEDs steal current to the yellow LED and then it shines only a bit. For a future project, my idea would be to make an intermediate circuit, combining the resistors of the red LEDs on a single resistor and using another resistor for yellow LED.

Actual circuit

Correct circuit

Proposed circuit. Does it work?

We should try this simplified version on a breadboard before putting a cold porcelain tree around it.

Un árbol de navidad con LEDs atrasado

Para este fin de año estuvimos haciendo con mi hija un árbol de navidad iluminado con LEDs, tiene unos 5cm (3 pulgadas) de alto. Lo terminamos tarde, cómo el 10 de enero.

Para que todo el circuito entre adentro del árbol pusimos una pila de reloj con su porta pila, un interruptor con retención, varios LEDs chiquitos rojos (3mm) y un LED normal amarillo (5mm). No titila, hay que prenderlo y apagarlo a mano. Para la estructura del árbol usamos la así llamada porcelana fría mezclada con colorantes. (Sólo dibujé cuatro LEDs rojos en los circuitos para simplificarlos.)

Diagrama del circuito


El porta pila y el interruptor más chico que conseguimos eran para usar en un protoboard o un circuito impreso. Eran muchos más chicos que las otras versiones que encontramos, pero fue difícil soldarlos.

A los LEDs les recortamos los terminales, que son de alambre duro, y los reemplazamos por alambres finitos aislados para poderlos acomodar en la posición correcta. Los terminales originales tienen distinta longitud, para distinguir el ánodo del cátodo. Al recortarlos se pierde esta distinción, así que recurrimos al viejo truco de probarlos con la pila en las dos posiciones posibles. (En realidad la forma de las partes internas del LED también sirven ayudan a orientarlo, pero yo confío más en lo que opina la pila.)

Circuito sin árbol

Para tener una idea del tamaño de los alambres, las posiciones, y cómo íbamos a ubicar los componentes adentro del árbol, hice un dibujo en papel y los acomodamos (la concepción artística es mía)

Circuito acomodado sobre esquema del árbol

Después de algunos intentos de acomodar las partes, el interruptor quedó en el tronco del árbol y la pila en la base para que se puede cambiar. En un momento tensamos en hacer una maceta que esconda la pila y el interruptor, pero la maceta quedaba demasiado grande.

La pila se puede cambiar desde abajo

El interruptor está en el tronco

El problema es que yo soy Técnico Químico (en la escuela secundaria) (yo disuelvo circuitos, no los construyo :)) y mi hija era la primera vez que soldaba. Encima los componentes estaban pensados para protoboard o circuitos impresos, no para soldarlos. Así que tuvimos que hacer varias veces las soldaduras hasta que estuvieron todas bien. En general lo más fácil era hacer un pequeño bucle en la punta del almabrecito, ajustarlo al terminal con una pinza y después soldarlo. Con todo esto uno de los LEDs murió, así que quedaron sólo cinco LEDs rojos y el amarillo.

Cada tanto movíamos el circuito para verificar que las soldaduras estén bien y sean firmes. Por ejemplo una de las soldaduras del interruptor estaba floja y entonces el árbol se apagaba o titilaba (¡titilaba!) espontáneamente. Por suerte, nos dimos cuenta de esto cuando sólo tenía la base y el tronco y sólo tuvimos que romper la primera versión del tronco, resoldar y rehacer el tronco.

Circuito con la base y el tronco

La mayoría del circuito estaba aislado, pero cerca de los LEDs y en los puntos donde se juntaban los cables había partes peladas. Por suerte la porcelana fría es aislante (al menos par 5V), así que alcanzó con tener cuidado de poner un poco de porcelana fría (del color correcto) entre los terminales del LED y alrededor de los otros puntos que no tenían aislación.

Para el árbol hicimos una base que parece de pasto color verde claro con un tronco marrón oscuro. Después un cono marrón muy oscuro, con la forma casi definitiva del árbol. (Yo quería que el árbol fuera más ancho como se ve en la concepción artística, pero mi hija insistió con la forma más alargada.) Después armamos una "hojitas" chatas verde (con forma de gotitas) y las presionamos para que se peguen. También le pudimos una cuentas de colores. En cada paso íbamos prendiendo y apagando el árbol para estar seguros de no haber roto ninguna parte del circuito.

Árbol terminado (apagado)

Árbol terminado (prendido)

Utilizando la magia del GIMP queda


Imagen trucha del árbol titilando :)

Comentarios y proyectos

La porcelana fría anduvo bien. Se pude manejar un rato largo agregándole un poquito de agua. En caso de errores se pueda sacar sin que quede todo muy manchado. Después de un día esta firme pero ligeramente flexible, pero con uno o dos días endurece bien.

También la porcelana fría es aislante (al menos para 5V), así que fue útil para encerrar el circuito sin problemas. Hay muy poca distancia entre los terminales de los LEDs y además está la soldadura y los alambrecitos que tienen la punta sin aislar, así que con el movimiento cada tanto se cortocircuitaba. (Con una pila de 5V es que esto no causa problemas.)

Uno de los LEDs murió antes de que le pusiéramos el árbol alrededor. No se si fue por mover mucho los terminales para soldarlos o mucho calor en la soldadura o ...

Uno de los LEDs quedó mal soldado, así que hay que darle cada tanto un golpe técnico para arreglarlo.

El portapila es medio quebradizo y la porcelana fría se metió un poco por los costados. No se que tan fácil va a ser cambiar esa pila, espero que dure varios años ...

¡No titila! Vamos a ver si el año que viene hacemos un árbol con un 555, pero antes yo debería averiguar cómo se conecta un 555 (¡yo se disolver un 555!). Se va a complicar porque hay más componentes para soldar.

Cómo algún experto en electrónica habrá notado, no le pusimos resistencias (asumo toda la culpa). La idea era minimizar la cantidad de soldaduras, para que sea más fácil de armar el proyecto. Encima con las soldadura de las resistencias quedarían muchos mas puntos sin aislante, así que deberíamos tener más cuidado de aislarlos, con cinta o más porcelana fría.

El mayor problema práctico de esto se debe a que hay LEDs de dos colores. Los fotones de la luz amarilla tienen más energía que los de la luz roja, por lo que el LED amarillo necesita más voltaje que el rojo, más o menos 2,0V contra 1,7V (en la práctica todo es un poco más complejo). Entonces los LEDs rojos le roban la corriente al LED amarillo y este brilla poco. 

Para un proyecto futuro, mi idea sería hacer un circuito intermedio, amuchando las resistencias de los LEDs rojos en un sola resistencia y poner otra resistencia para el LED amarillo.


Diagrama del circuito real

Diagrama del circuito correcto

Diagrama del circuito intermedio. ¿Anda?

Debería ver como anda esta versión simplificada en el protoboard antes de ponerle un árbol de porcelana fría alrededor.

9 de enero de 2015

Ignored expressions in Racket bytecode

Introduction

Following the idea of the last articles, we will count the occurrences of expressions whose result is ignored in the bytcode of Racket. In general, Racket programs are almost functional, as a matter of style. Almost always the useful part of each function is the result that it returns and usually they have no side effects. But when it's convenient you can use side effects locally, enclosed inside a function that is functional when you looks from the outside.
It is important to remember that when analyzing bytecode, we are looking at what remains after multiple optimizations steps and multiple macro expansions steps. So the results we get are very different from those obtained by analyzing the original code. These steps include functions inlining and constant propagation, so expressions that would be ridiculous in the source code as (box? (List (f 1) (f 2) (box 7)) can occur. Moreover, such cases are optimized because it is sure that the result is #f and then it's reduced to (begin (f1) (f2) (box 7) #f). And that (box 7) is superfluous, because it never fails nor has any side effects, then in the same step it is optimized to (begin (f 1) (f 2) #f). (Actually, maybe (begin (values (f 1)) (values (f 2)) #f) if the optimizer is not certain that f returns a single value.)
The subrutine that optimizes the expressions that are ignored, only eliminate the calls to unnecessary functions. This is good because it eliminates a lot of constructors, so at run time it's not necessary to create objects that are going to be destroyed immediately. For example, in (begin (cons (f) 'z) (if (h) 0 1)) #f) it eliminates the cons, but it doesn't removed the if, so the final expression is (begin (f) (if (h) 0 1) #f) because the 'z can be ignored. It would be better it it also eliminates the if, so we would get (begin (f) (h) #f) because we will ignore the result if then it doesn't matter if it produces either 0 or 1. But every additional reduction rule makes the optimization slower and more complex.
The big question is how many of these things remain after all the optimizations, to see if it is worth adding an optimization for this kind of if or they are very few and we can just ignore them. Also we will count what kind of functions are in expressions that are ignored, in order to see if there are interesting things that are not optimized away.

Program to count the expressions

The program is a shortened version of decompile. It's similar to the one we used in the previous articles. The interesting part is how it handles the begin (represented by seq), the begin0 (represented beg0) and the let where the variable is ignored (represented with a let-one, with a #t in the unused? flag).
{define (explore-expr expr globs stack closed)
  (match expr
    [(struct let-one (rhs body type unused?))
     (let ([id (or (extract-id rhs) (gensym (or type (if unused? 'unused 'local))))])
       (when unused?
         ((current-explore-found) 
          (list '|let-unused;| (decompilex-expr rhs globs stack closed))))
       (explore-expr rhs globs (cons id stack) closed)
       (explore-expr body globs (cons id stack) closed))]
    [(struct seq (exprs))
     (begin
       (for ([expr (in-list (reverse (cdr (reverse exprs))))])
         ((current-explore-found) 
          (list '|begin;| (decompilex-expr expr globs stack closed)))
         (explore-expr expr globs stack closed))
       (explore-expr (last exprs) globs stack closed))]
    [(struct beg0 (exprs))
     (begin
       (explore-expr (car exprs) globs stack closed)
       (for ([expr (in-list (cdr exprs))])
         ((current-explore-found) 
          (list '|begin0;| (decompilex-expr expr globs stack closed)))
         (explore-expr expr globs stack closed)))]
    [...]
    [else (void)])}
When it finds an expression whose result will be ignored, it calls decompilex-expr (with an extra x because it's not the real decompile-expr) which translates it to something more friendly. Then it passes the result to the main program calling the function that is in the parameter current-explore-found , which is responsible for storing, classifying and counting the expressions.
{define (decompilex-expr expr globs stack closed)
  (match expr
    [(struct toplevel (depth pos const? ready?))
     (if ready? (if const? '#%topcr '#%topr) (if const? '#%topc '#%top))
     #;(list-ref/protect globs pos 'toplevel)]
    [(struct primval (id))
     (hash-ref primitive-table id (lambda () (error "unknown primitive")))]
    [(struct localref (unbox? offset clear? other-clears? type))
     (if clear? '%clear-localref '#%localref)]
    [(struct branch (test then else))
     (list 'branch (filter-simple-values then) (filter-simple-values else))]
    [(struct application (rator rands))
     (list 'application (decompilex-var rator globs stack closed) (length rands))]
    [(struct apply-values (proc args-expr))
     (list 'applicationv (decompilex-var proc globs stack closed) 'v)]
    [else (car (or (prefab-struct-key expr) (list expr)))])}
This function tries to decompile the expression just a little, only to understand and classify it better. For example, for the functions calls, it adds the number of parameters.
In the case were there is a local variable accesses, this function marks whether the access also cleans the variable reference. This cleaning step is necessary  to allow the heavily recursive programs (aka normal) to be run. Before calling a function it tries to remove the references to variables that will not be used again. In this way, the garbage collector can recover the used memory. In general this is done in the last access to the variable, but in some cases one of the steps in the compilation have to add these marks. In these cases, the access to the variables has a subtle side effect that is not visible internally in the program, but allow the program to make more recursions. For example in
{define (too-much-zeros n)
  (let ([z (random n)])
    (if (zero? z)
      (display z)
      (too-much-zeros n)))}  
the z would accumulate even though they will never be used again. After the compilation, the program is transformed in something equivalent to (version cleaned for clarity):
{define (too-much-zeros n)
  (let ([z (random n)])
    (if (zero? z)
      (display z)
      (begin (#%sfs-clear z) (too-much-zeros n))))}  

Results

To count the expressions I used the repository Racket, from the last days of November just before the Great Split. First, let's count the ignored expressions that are not functions applications. The table shows the number of times that certain types of expression and a representative decompiled example. In the examples, v is a local variable and u is an unused variable.
Count Example
2827 (begin (#%sfs-clear v) ... _)
1504 (begin0 _ (#%sfs-clear v) ...)
87 (begin (if ? #<void> ?) ... _)
20 (begin (if ? ? #<void>) ... _)
18 (begin (if ? ? ?) ..._)
81 (begin (let ([u ?]) ...) ... _)
Most of the things that appear are the cleaning of  variables references. There are only a few if, they are probably due to the expansion of when and unless, but in all the cases at least one of its branches seems to be interesting, so they are not good candidates for simplification. (Actually, since a few months, expressions like (if v 0 1), which can not generate errors nor have side effects, are eliminated during the optimization when the result is going to be ignored.)
For simplicity, the method that I described to detect the expressions that have results that are ignored is slightly naive and it doesn't detect nested constructions. For example in (begin (begin x Y) z) it is clear that it doesn't matter the result of Y, but the previous program doesn't know it. Another example is (begin (if x Y Z) w), where we will not not take into account either the result of Y nor Z To fix this, we must add an extra argument to explore-expr to indicates whether the expression we are analyzing will be ignored and recursively propagate this argument. This extends the program a little, but it's nothing surprising. With this modification, we can count more ignored expressions. In the next table we compare the amount of expression found with each method, with a representative example of the decompiled code. In the examples, v is a local variable and u is an unused variable.
Pos Count Dir Count Exp Example Direct
1 202 202 (begin (set-box! ? ?) ... _)
2 85 85 (let ([u (_tok-val:ref@(lib "parser-tools/cfg-parser.rkt") ?)]) ... )
3 72 80 (begin (v ?) ... _)
4 0 32 (begin (raise-syntax-error ? ? ? ?) ... _)
5 0 29 (begin (raise-type-error ? ? ?) ... _)
6 29 29 (begin (set-mcdr! ? ?) ... _)
7 29 29 (let ([u (_stx-car:P@(lib "racket/private/stx.rkt") ?)]) ... )
8 18 24 (begin (v ? ?) ... _)
9 0 23 (begin (error ? ? ?) ... _)
10 17 17 (begin (namespace-variable-value ? ? ?) ... _)
11 11 17 (begin (fprintf ? ? ?) ... _)
12 11 17 (begin (fprintf ? ?) ... _)
13 0 17 (begin (printf ? ?) ... _)
14 5 15 (begin (_check-type ? ? ?) ... _)
15 5 15 (begin (hash-set! ? ? ?) ... _)
16 11 11 (begin (vector-set! ? ? ?) ... _)
17 0 8 (begin (raise-type-error ? ? ? ? ?) ... _)
18 5 8 (begin (? ? ?) ... _)
19 6 7 (begin (? ? ? ? ?) ... _)
20 7 7 (begin (apply ? ? ?) ... _)
21 0 7 (begin (error ? ?) ... _)
22 0 7 (begin (for-each ? ?) ... _)
23 1 6 (begin (? ? ? ?) ... _)
24 5 5 (begin (_check-sigs:P@(lib "racket/private/unit-runtime.rkt") ? ? ? ?) ... _)
25 0 5 (begin (_idY21.62:f@(lib "syntax/boundmap.rkt") ? ? ? ?) ... _)
26 5 5 (begin (_check-unit:P@(lib "racket/private/unit-runtime.rkt") ? ?) ... _)
27 5 5 (let ([u (cadr ?)]) ... )
Most are some version of set! for some structure, for example set-box! or set-mdr!, which are called for its side effect that stores a value in the structure. It's not surprisingly to find them here and clearly they can not be deleted. Other functions are obviously called for its side effects, such as fprintf. There are also many expressions that generate explicitly an error, so they can't be eliminated.
With both counting methods the kind of thing we find are similar. The biggest difference is that in the second version, there many more functions that generate error messages. I should analyze this more carefully, but I guess that they correspond to code like
{define (f l)
  (unless (list? l)
    (error 'error))
  (something-useful-with l))}
which expands to something like (version cleaned for clarity )
{define (f l)
  (begin
    (if (list? l)
      #<void>
      (error 'error))
    (something-useful-with l))}
The first method do not realize that either of the results of both branches of the if  are going to be ignored, but the second method does. This is a very usual construction in Racket source code, so I guess this is the cause of most of the differences.
The moral is that (almost?) all expressions that which results are ignored have side effects, and there isn't an obvious idea to optimize any of them.