✍ diale.org

✍ Suporte para breadboard DIY
... construção e alguns truques

2018/06/13-14:00:47

Introdução

A iniciação no DIY para montagem e estudo de efeitos para guitarra, baixo ou outros instrumentos electrónicos tem sempre uma custo inicial elevado, isto porque é necessário adquirir alguma material que inclui ferramentas, transístores, circuitos integrados, transformadores, resistências, condensadores , etc, e, normalmente, uma breadboard. A breadboard é uma ferramenta de estudo e experimentação importante. Permite montar uma versão provisória de um circuito sem danificar os componentes utilizados e utiliza-los numa outra futura construção. Uma das dificuldades na montagem e avaliação de um circuito para ser usado com um instrumento musical é a necessidade de levar a montagem até ao amplificador para ser testado, para ver como soa, ou então testa-lo com um amplificador de bancada. Não é raro a breadboard cair ao chão durante os testes, puxa-se um fio, ou as fichas são pesadas e puxam a montagem que já estava a escorregar na mesa das sala ou da cozinha desmontando tudo e levando ao curto-circuito final. Assim é importante a utilização de um suporte para acomodar a breadboard na sua tarefa de teste e experimentação. Nas páginas seguintes descreve-se a construção de uma base para breadboard, não só a breadboard mas o suporte para ligar os cabos e ligação ao amplificador, alimentação, potenciómetros, etc.

A construção é relativamente simples não sendo preciso máquinas sofisticadas. São apenas necessárias ferramentas básicas: furador (eléctrico ou manual), limas (para acertar a dimensão dos furos e limar as arestas de corte da calha de alumínio), serra para metal e ferro de soldar. Caso o leitor queira montar uma engenhoca destas é sempre bom, para cortar o investimento inicial no hobby, pedir a um amigo que o ajude na construção. Dá tanto trabalho fazer uma como duas!

Uma casa para a breadboard

Material

Calhas metálicas: medição e corte

Comecemos então por marcar 20cm, o comprimento do perfil de alumínio, com um esquadro metálico e uma caneta de acetato. A calha tem 43.5mmx 23.5mm com comprimento total de 1.5m. Usei um esquadro metálico para marcar e medir, mas uma régua de plástico serve perfeitamente.

Faço as mesmas medições para as duas calhas. As arestas cortantes serão limadas durante o acabamento. depois de feitos os furos.

Uma tábua de 20cmx20cm tem as dimensões certas para acomodar o resto da montagem e adapta-se bem ao uso que se lhe quer dar. Qualquer tipo de madeira serve.

Aquela que vou usar já foi usada noutras montagens provisórias e tem uma espessura de 1.5cm e um bom peso para suportar o objectivo das suas funções. Poderíamos usar MDF, acrílico ou qualquer outro material isolante.

Calhas metálicas: furação

Optei por fazer 7 furos distanciados de 3cm (1cm das extremidades), pode parecer excessivo mas nunca se sabe o que o futuro nos reserva em futuras montagens e fica já tudo furado para não ter depois de as desmontar.

Depois de marcados a caneta os pontos marco com um punção os locais de furação (neste caso um parafuso de aço, uma broca velha também serve).

Usei uma broca de 8mm de modo conseguir colocar as todas fichas, potenciómetros e um interruptor (que dá sempre jeito). Como os jacks têm um diâmetro maior, com uma lima aumenta-se sucessivamente o diâmetro testando as dimensões entre umas quantas limadelas.

A imagem seguinte mostra um conjunto básico de coisas que podemos ligar: dois jacks, potenciómetro, ficha de alimentação e um interruptor. Note-se que já estão feitos os furos na parte inferior da calha para fixação na base de madeira.

Montagem e soldaduras

Mesmo antes de soldar os fios, e depois de lixadas e aparafusadas as calhas, podemos ver que a coisa se começa a compor. Usei uma lixa fina de metal para dar o acabamento final (lixa de água, uma lixa fina de madeira também pode ser usada, deita-se a lixa fora no fim) e uma lima para acertar as arestas cortantes nos topos de cada calha.

Costumo usar fio de telefone ou de cabo rede para as montagens na breadboard, o metro linear é barato e é possível encontra-lo em todas as lojas de bricolage a qualquer hora do dia, não vá aparecer uma vontade súbita de montar qualquer coisa e faltar material, e num metro temos disponíveis muitas cores (as cores são nossas amigas) que são óptimas e muito úteis para as montagens na breadboard. Apenas é necessário paciência para desenrolar o fio.

Optei por colocar o led directamente na breadboard mas sem dificuldade se monta na parte frontal da geringonça.

Um botão comprado na saudosa Dimofel et voilá, a engenhoca pronta a ser usada para testes e invenções!

Considerações finais

A montagem de circuitos numa breadboard é simples, permite de uma forma simples experimentar e confirmar circuitos e ideias que de outra forma não seria possível sem danificar e inutilizar componentes electrónicos. Outras abordagens de construção e design são possíveis!

Boas construções.

Etiquetas/Tags: diy, electrónica, breadboard

✍ Prótese de uma mão 3D impressa
... primeira tentativa na impressão.

2018/06/13-13:59:59

Comecei hoje, já vos conto daqui a 10 hora como correu, a impressão 3D de uma mão prostética. Há muitos projectos por aí mas este Raptor Hand pareceu-me uma das melhores iniciativas.

É difícil não ficar emocionado com estes testemunhos.

Vamos ver como corre a impressão!

Impressão ficou fantástica... vamos lá montar isto!

A entrada no thingiverse é esta: https://www.thingiverse.com/thing:476403

A parte de encaixe está montada. Agora faltam os elásticos e os fios...

Etiquetas/Tags: 3dprint, prosthetic, hand, mão, raptor

✍ Filtro Kalman 1D
... implementação simples de um filtro de Kalman usando Arduino (ou outra coisa qualquer)

2018/06/12-09:28:24

A ideia deste texto é explicar de uma forma simples a implementação de um filtro de Kalman num Arduino e construir um sensor de intensidade luminosa usando um LDR. O hardware necessário é o seguinte:

Hardware e código inicial

É fácil de encontrar um código exemplo para se ligar um LDR ao Arduino. Fica aqui uma versão simples ;)

int sensorPin = A0; 
int sensorValue = 0;

void setup(){ 
  Serial.begin(9600); 
} 

void loop(){ 
  sensorValue = analogRead(sensorPin); 
  Serial.println(sensorValue); 
} 

O gráfico seguinte mostra a variação da luminosidade quando tapo e destapo o LDR com a mão. Vê-se claramente as oscilações de 50Hz da rede eléctrica na luz do candeeiro.

Filtro de Kalman 1D

Quero então estimar o valor da luminosidade da sala onde me encontro. Para isso admito que a intensidade luminosa é constante (ou antes que necessita de ser "quase" constante de modo a que seja possível fazer uma medição) e que o valor medido y possa ser decomposto na soma de um valor médio m mais um termo de flutuação gaussiano v com variância r (valor inicial). Assim

y:=m+v

Admito também que para cada valor da luminosidade se tem a estimativa x dada por

x:=m+w

com o mesmo valor médio e flutuações gaussianas mas com variância q (valor inicial). Note-se que w e v são variáveis aleatórias gaussianas com média zero e independentes.

O filtro de Kalman admite que as sucessivas aproximações (modelo) são obtidas linearmente das anteriores, i.e. xf:=a xi . Como estou a admitir que os sucessivos valores da luminosidade são constantes ponho a:=1

x:=x

e

p:=p+q

onde p é variância da aproximação seguinte (são todas variáveis gaussianas independentes, a variância da soma é a soma das variâncias).

Ficam assim estabelecidas as regras de evolução da primeira parte do algoritmo de Kalman. Vamos à segunda parte. Esta segunda parte corresponde a estimar/prever a aproximação seguinte que é escrita em termos da aproximação anterior e o erro de previsão, i.e.,

x:=x+k(y-x)

onde k é um parâmetro a determinar, usualmente chamado de ganho do filtro, e y-x o erro de previsão. Como determinar então o valor de k? O valor de k é determinado de forma a minimizar a variância da nova estimativa x+k(y-x).

Calculando a variância desta última quantidade obtém-se

p:=(1-k)^2*p+k^2*r

É condição necessária para que se tenha um extremo relativo da variância que a derivada de p em ordem a k seja zero. Isto dá:

k:=p/(p+r)

e

p:=p*r/(p+r)

Curiosamente, ou talvez não, esta última fórmula corresponde formalmente ao valor do paralelo de duas resistências com valores p e r.

Fico assim com as duas últimas fórmulas que precisava:

k:=p/(p+r)
x:=x+k(y-x)
p:=(1-k)*p

O gráfico seguinte mostra o que acontece quando tapo e destapo o LDR (linha azul) numa escala de 0-1023. As linhas a verde e vermelho correspondem à implementação de filtros de Kalman com parâmetros diferentes.

Happy hacking!


/* Simply implementation of a 1D Kalman filter */
/* for Arduino using a LDR. */

/* Some other examples can be done with this file, */
/* e.g. sonar, temperature measurements, sky is the limit. */
/* Happy hacking! */
  
/* Author: Tiago Charters de Azevedo  */
/* Maintainer: Tiago Charters de Azevedo  */
/* URL: http://diale.org/ */
/* Version: 0 */

/* Copyright (c) - 2018 Tiago Charters de Azevedo */

/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3, or (at your option) */
/* any later version. */

/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the */
/* GNU General Public License for more details. */

/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software */
/* Foundation, Inc., 51 Franklin Street, Fifth Floor, */
/* Boston, MA 02110-1301, USA. */

/* Commentary: */

int sensorPin = A0; 
int sensorValue = 0;

// 1st filter parameters
float q=0.125;
float r=32;
float p=1023;
float x=0;
float k=0;

// 2nd filter parameters
float q1=4;
float r1=100;
float p1=1023;
float x1=0;
float k1=0;

void setup(){ 
  Serial.begin(9600); 
} 

void loop(){ 
  sensorValue = analogRead(sensorPin); // read sensor value

  // 1st Kalman filter
  p=p+q; 
  k=p/(p+r);
  x=x+k*(float(sensorValue)-x);
  p=(1-k)*p;

  // 2nd Kalman filter
  p1=p1+q1; 
  k1=p1/(p1+r1);
  x1=x1+k1*(float(sensorValue)-x1);
  p1=(1-k1)*p1;

  
  //Print values
  Serial.print(sensorValue); // raw value
  Serial.print(", ");
  Serial.print(int(x)); // 1st filter output
  Serial.print(", ");
  Serial.print(int(x1)); // 2nd filter output
  Serial.println("");
} 

1.R. Kalmam, A New Approach to Linear Filtering and Prediction Problems, Transactions of the ASME–Journal of Basic Engineering, 82 (Series D): 35-45. 1960

Etiquetas/Tags: kalman, arduino, filtro

✍ Pipes law
Os modelos de modelação de tráfego mais simples são os chamados de follow-the-leader...

2018/05/26-21:09:07

Os modelos de modelação de tráfego mais simples são os chamados modelos follow-the-leader.

O mais simples corresponde a tomar o valor da aceleração do i-ésimo carro com sendo proporcional à diferença de velocidades do carro seguinte e a sua latex2png equation Este modelo não inclui o tempo de reacção do condutor, para o incluir basta introduzir um tempo de reacção latex2png equation que reflecte o tempo de reacção, finito, de cada condutor. Obtém-se assim um modelo de estímulo-resposta (Pipes law) dado pelas equações

latex2png equation

A quantidade latex2png equation mede a sensibilidade ao estímulo. Estas equações pertencem à classe de equações diferenciais ordinária com atraso cujas soluções para latex2png equation se tornam instáveis. Prova-se que (Chandler et al., 1958) as variações das velocidades individuais de cada carro são amplificadas quandolatex2png equation, dando origem a ondas de pára-arranca e a acidentes.

Etiquetas/Tags: tráfego, modelos, matemática, follow-the-leader, Pipes law

✍ Paradroid: how I did it
Steps to build a 2.5D Paradroid for 3D printing

2018/05/18-10:29:14

It all started when I found some drawings of the character of the infamous computer game from the 80's.

The next step was obvious to me, just build a raster graphics of the beast using GNU/Octave. As is the original image needed some modification on order to be 3d-printed.

A=[1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1;    
1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1;
1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1;
1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1;    
1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 0 1;
1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 0 0 0;
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0;
0 0 1 1 1 0 0 1 0 0 1 1 1 0 0 1 1 1 0 0 0;
0 0 1 1 1 0 0 1 0 0 1 1 1 0 0 1 1 1 0 0 0;
0 0 1 1 1 0 0 1 0 0 1 1 1 0 0 1 1 1 0 0 0;
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 1 0 0 0;
1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 0 0 0;    
1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 0 1;
1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1;
1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1;    
1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1];
imshow(A)

print -deps -color paradroid.eps
print -dpng -color paradroid.png

So added some extra squares to get the job done.

Then used the Inkscape-to-OpenSCAD plugin and got the final 3d model, after some editing on the output code.

And it prints nicely with a resolution of 0.2mm and a 20% infill.

You can get it here: https://www.youmagine.com/designs/paradroid-ornament-key-chain

Share and enjoy!

Etiquetas/Tags: paradroid, 3d, 3dprinting, 3dprint, game, math

✍ Berry's paradox and elegant LISP programs
in Common Lisp

2018/05/18-10:29:07

Giro!

(defun s-expressin-length (s)
  (length (write-to-string s)))

(defun complexity (s)
  (s-expressin-length (eval s)))

(complexity  '(car '(a b)))  

(defun is-elegant (s)
  (cond ((eq (s-expressin-length s) (complexity s))
         t)
        (t
         nil)))

(defun berry1 (lst)
  (cond ((null lst) nil)
        (t
         (cond ((and (is-elegant lst) 
                     (>= (complexity lst) (s-expressin-length #'berry1)))
                #'berry1)
               (t
                lst)))))

(defun berry (lst)
  (cond ((null lst) nil)
        (t
         (cond ((and (is-elegant (car lst)) 
                     (>= (complexity (car lst)) (s-expressin-length #'berry))))
                #'berry)
               (t
                (berry (cdr lst))))))


Alguns extras úteis que tinha para aqui.

As notas aqui descritas estão pensadas para SBCL - Steel Bank Common Lisp em Debian - GNU/Linux.

  1. Pedir a CL para não gritar (inlcuir a instrução no ficheiro ~/.sbclrc):
(setf *print-case* :downcase)
  1. A maneira mais simples de instalar e manter os packages em CL é usando o ASDF. Há dois manuais que valem a pena ser lidos:
  2. Exemplo de instalação usando o asdf: Para instalar a LTK - The Lisp Toolkit faz-se:
(require 'asdf-install)
(asdf-install:install 'ltk)
O asdf faz o download dos ficheiros e diz
Downloading 240780 bytes from http://www.peter-herth.de/ltk/ltk-0.91.tgz ...
e pergunta:
Install where?
1) System-wide install: 
   System in /usr/lib/sbcl/site-systems/
   Files in /usr/lib/sbcl/site/ 
2) Personal installation: 
   System in /home/tca/.sbcl/systems/
   Files in /home/tca/.sbcl/site/ 
respondo 2.

Etiquetas/Tags: LISP, Berry paradox

✍ A verdade, nada mais do que a verdade
Notas sobre o Teorema de Godel (exposição informal)

2018/03/18-00:17:02

Vamos construir uma máquina de calcular que escreve expressões compostas pelos seguintes símbolos neg P N ( ).

Por expressão entenda-se uma lista não vazia composta por estes cinco símbolos. Uma expressão X é "printável"1 se a máquina a conseguir escrever ("printar"). Admitimos que a máquina está programada de a modo a escrever expressões que pode imprimir, i.e., gasta todo o seu tempo a imprimir expressões.

Chama-se norma de uma expressão X à expressão composta X(X); por exemplo, a norma de P neg é P neg (P neg). Uma frase válida tem uma das seguintes formas:

  1. P(X)
  2. P N(X)
  3. neg P(X)
  4. neg P N(X)

Se associarmos, informalmente, a três dos símbolos anteriores um significado podemos ler uma qualquer frase válida. Assim associamos os seguintes significados a P, N e neg:

Com esta interpretação podemos dizer que P(X) é uma frase verdadeira se, e só se, X é printável1; do mesmo modo PN(X) é verdadeira se, e só se, a norma de X poder ser escrita, neg P (X) é verdadeira sse2 X não poder ser escrita e neg P N(X) é verdadeira se a norma de X não poder ser escrita. Assim as definições anteriores permitem-nos falar em português, e com rigor, sobre o que afirmam cada uma das frases escritas pela máquina e o que significa uma expressão verdadeira. Estas são de facto, auto-afirmações, efectuadas pela máquina, são frases que nos dizem algo sobre a máquina que as escreve. A máquina durante o seu funcionamento descreve o seu próprio funcionamento, semelhante a um organismo consciente.

Assim concluímos que a máquina está bem definida, i.e., funciona bem, e que todas as frases que por ela são escritas são expressões verdadeiras. Por exemplo, se a máquina escrever P(X), isto significa que X pode ser realmente escrito (X será escrito mais tarde ou mais cedo); da mesma forma se num instante posterior a máquina escrever P N(X) então X(X) também aparecerá mais tarde. Admitamos agora que X pode ser escrito pela máquina, será que podemos concluir que P(X) também o será? Se X pode ser escrito pela máquina então a frase P(X) é verdadeira, mas não sabemos, de facto, se P(X) pode ser escrito pela máquina, ou seja, se P(P(X)) é verdadeira.

Será possível a máquina escrever todas as afirmações verdadeira que falam sobre ela?

A resposta a esta pergunta é, um surpreendentemente, não! Para podermos verificar isso temos que encontrar uma frase que seja verdadeira, i.e., que afirme algo verdadeiro sobre a máquina, e que a máquina não consiga escrever. Basta construir uma frase, uma expressão, que afirme a sua não "printabilidade".

Uma candidata seria: Esta frase "esta frase não pode ser escrita" não pode ser escrita. Ou seja neg P N (neg P N), que afirma que a norma de neg P N não pode ser escrita. Por definição de expressão verdadeira, a frase anterior é verdadeira se a norma de neg P N não pode ser escrita, mas a norma de neg P N é exactamente a frase neg P N (neg P N)!

Algumas frases apressadas

Ref: Smullyan, R M (2001) "Gödel's Incompleteness Theorems" in Goble, Lou, ed., The Blackwell Guide to Philosophical Logic. Blackwell

1. Vou usar "printável" para dizer o mesmo que "pode ser escrita".

2. sse = se, e só se

Etiquetas/Tags: Godel, teorema, notas, Smullyan

✍ Word list
Funções em elisp para manipulação de ficheiros de palavras.

2018/03/18-00:17:02

Na antiga versão do jogo do monopólio existia uma carta da sorte que começava com a expressão "Levou um tiro de um amigo..." e normalmente o que se seguia consistia no pagamento de uma conta do hospital.

Um amigo não me deu um tiro mas fez-me uma pergunta, e no meu caso a procura da resposta leva a quase uma visita ao hospital. A pergunta era: " Será que existem palavras de 5 letras em português que verifiquem o padrão seguinte?"

1 5 9 1 7 
2 6 0 5 6 
3 7 3 4 0 
4 8 2 8 9 
Nota: cada número representa uma letra diferente.

Não interessa muito de onde aparece a motivação da pergunta, interessa-me mais a procura da resposta. Há largos meses que tinha começado a ler o volume 4 do TAOCP Combinatorial Algorithms, Part 1 onde, entre outras coisas, é usada a Stanford GraphBase, uma lista de 5757 palavras em inglês com cinco letras, para exposição dos vários algoritmos que aí são descritos.

Propus-me então replicar1 alguns dos resultados descritos no TAOCP usando palavras em PT. Para isso precisava de um dicionário e uma maneira de começar a extrair a informação. O resultado é este pequeno conjunto de funções em elisp. Muito ainda está por fazer, por exemplo, o aspell usa um sistema de compressão para prefixos e sufixos, cuja sintaxe só descobri hoje, e que aumenta o número de palavras disponíveis para se brincar.

;;; wlist.el --- Emacs tools for manipulating word-files 
;; word-files, meaning a file with words in it, one word per line.

;; Author: Tiago Charters de Azevedo <tca@diale.org>
;; Maintainer: Tiago Charters de Azevedo <tca@diale.org>
;; Created: Fev, 17, 2012
;; Version: .1
;; Keywords: words
;; URL: http://diale.org/wlist.html

;; Copyright (c) 2012 Tiago Charters de Azevedo

;; This file is not part of GNU Emacs.

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program; if not, write to the Free Software
;; Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.

;;; Commentary:
;; None.

;; Code:

(defvar wlist-max-lenght 
  0
  "")

(defvar wlist-regexp-pt
  "[aerisontcdmlupvgbfzáhçqjíxãóéêâúõACMPSBTELGRIFVDkHJONôywUKXZWQÁYÍÉàÓèÂÚ].+"
  "Regular expression for a portuguese word; see aspell.")

(defun wlist-looking-at-size ()
  "Returns the length of a word on the beginning of a line (pt-PT)."
  (interactive)
  (if  (looking-at wlist-regexp-pt)
      (length (match-string-no-properties 0))
    0))

(defun  wlist-looking-at-size-plus-1 ()
  (interactive)
  (forward-line 1)
  (wlist-looking-at-size))

(defun wlist (size)
  "Removes all sized SIZE words from `current-buffer'; asks SIZE."
  (interactive "n") 
  (with-current-buffer (current-buffer)
    (goto-char (point-min))
    (save-excursion  
      (while (< (line-number-at-pos) (line-number-at-pos (point-max)))
        (when (not (= size (wlist-looking-at-size)))
          (delete-region (point) (line-end-position)))
        (forward-line 1))))
  (wlist-delete-blank-lines))

(defun wlist-delete-blank-lines ()
  (interactive)
  (with-current-buffer (current-buffer)
    (goto-char (point-min))
    (save-excursion  
      (while (< (line-number-at-pos) (line-number-at-pos (point-max)))
        (delete-blank-lines)
        (forward-line 1)))))

(defun wlist-insert-header ()
  "Inserts a not so beautiful header."
  (goto-char (point-min))
  (insert (format "File name: %s\n" (file-name-nondirectory (buffer-file-name)))
          (format "Number of %s sized words: %s\n" size (line-number-at-pos (point-max)))))

(defun wlist-hamming-dist-list (lst1 lst2)
   "For equal length lists is the number of positions at which the 
corresponding lists are different."
  (if  (and lst1 lst2
            (= (length lst1) (length lst2)))
      (if (equal (car lst1) (car lst2))
          (wlist-hamming-dist-list (cdr lst1) (cdr lst2))
        (+ 1 (wlist-hamming-dist-list (cdr lst1) (cdr lst2))))
    0))

(defun wlist-hamming-dist (str1 str2)
  "For equal length strings is the number of positions at which the 
corresponding strings are different."
  (wlist-hamming-dist-list (string-to-list str1) 
                              (string-to-list str2)))

(defun wlist-remove-bslash ()
  "Remove /* properties form word-file. No plurals or m/f, etc,... 
Needs to be changed correctly for portuguese."
  (interactive)
  (with-current-buffer (current-buffer)
    (goto-char (point-min))
    (save-excursion  
      (while (search-forward-regexp "\\(.+\\)\\(/.+\\)" nil t)
        (let ((word-s (match-string-no-properties 1)))
          (replace-match word-s))))))

(defun wlist-max-size ()
  "Gets the maximum size of all words in a word-file."
  (interactive)
  (with-current-buffer (current-buffer) 
    (goto-char (point-min))
    (save-excursion  
      (while (< (line-number-at-pos) (line-number-at-pos (point-max)))
        (setq wlist-max-lenght (max (wlist-looking-at-size) (wlist-looking-at-size-plus-1) wlist-max-lenght))))))

(defun wlist-file-size (size)
  "Determines and creates a file of all the words with size SIZE."
  (interactive "n")
  (let ((dic-words (buffer-string)))
    (with-temp-buffer
      (insert dic-words)
      (wlist size)
      (append-to-file (point-min) (point-max) 
                      (concat default-directory (format "%s.wl" size))))))

(defun wlist-all-files-sizes ()
  "Determines all the words from size 2 to `wlist-max-size' 
and save them to separate files *.wl; it takes a few minutes to finish."
  (interactive)
  (if (= wlist-max-lenght 0)
      (wlist-max-size))
  (let ((size 2))
    (while (<= size wlist-max-lenght )
      (wlist-file-size size)
      (incf size))))
  
(defun wlist-same-pos (n)
  (interactive "x")
  (with-current-buffer (current-buffer) 
    (goto-char (point-min))
    (save-excursion  
      (while (< (line-number-at-pos) (line-number-at-pos (point-max)))
        (looking-at wlist-regexp-pt)
        (if (not (equal (nth (- (car n) 1 )
                        (string-to-list (match-string-no-properties 0)))
                   (nth (- (cadr n) 1)
                        (string-to-list (match-string-no-properties 0)))))
;;          (message (match-string-no-properties 0)))
            (delete-region (point) (line-end-position)))
        (forward-line 1)))
    (wlist-delete-blank-lines)))

(defun wlist-file-same-pos (n)
  (interactive "x")
  (let ((i (car n))
        (j (cadr n))
        (words (buffer-string)))
    (with-temp-buffer
      (insert words)
      (wlist-same-pos (list i j))
      (append-to-file (point-min) (point-max) 
                      (concat default-directory (format "%s_%s.wl" i j))))))


(defun wlist-find-all-hamming-dist-word (word dist)
  (with-current-buffer (current-buffer) 
    (goto-char (point-min))
    (save-excursion  
      (while (< (line-number-at-pos) (line-number-at-pos (point-max)))
        (looking-at wlist-regexp-pt)
        (if (not (= dist (wlist-hamming-dist word (match-string-no-properties 0))))
            (delete-region (point) (line-end-position)))
        (forward-line 1)))
    (wlist-delete-blank-lines)))

(defvar wlist-buffer-content-list nil
  "")

(defun wlist-buffer-length ()
  (count-lines (point-min) (point-max)))
  
(defun wlist-buffer-alist ()
  (interactive)
  (with-current-buffer (current-buffer) 
    (goto-char (point-min))
    (let ((wl-buffer-list nil))
      (save-excursion  
        (while (< (line-number-at-pos) (line-number-at-pos (point-max)))
          (looking-at wlist-regexp-pt)
          ;;    (push 'new-item accumulator)
        (push (match-string-no-properties 0) wl-buffer-list)
        (forward-line 1)))
      (reverse wl-buffer-list))))

(defvar wlist-word-link nil
  "")

(defun wlist-hamming-dist-word-insert (word dist)
  "Looks for the hamming DIST of word WORD, inserts all the words found after WORD."
  (setq wlist-word-link nil)
  (with-current-buffer (current-buffer) 
    (goto-char (point-min))
    (save-excursion
      (while (< (line-number-at-pos) (line-number-at-pos (point-max)))
        (looking-at wlist-regexp-pt)
        ;; Looks for word in file and save point, for inserting.
        (if (equal word (match-string-no-properties 0))
            (setq w-point (list (point) (line-end-position))))
        (forward-line 1)))
    (save-excursion  
      (while (< (line-number-at-pos) (line-number-at-pos (point-max)))
        (looking-at wlist-regexp-pt)
        (if (= dist (wlist-hamming-dist word (match-string-no-properties 0)))
            (push (match-string-no-properties 0) wlist-word-link))
        (forward-line 1)))
    (goto-char (cadr w-point))
    (insert (format " %s" (mapconcat 'concat word-link " ")))))

(defun wlist-hamming-dist-insert-buffer (dist)
  "Builds the world link with DIST and inserts the result after every word in buffer."
  (let ((wlist-list (wlist-buffer-alist)  ))
    (dolist (word wlist-list)
      (wlist-hamming-dist-word-insert word dist))))

(defun wlist-insert-after-word (word in-word)
  "Insert IN-WORD in `curren-buffer' after WORD."
  (with-current-buffer (current-buffer) 
    (goto-char (point-min))
    (save-excursion
      (while (< (line-number-at-pos) (line-number-at-pos (point-max)))
        (looking-at wlist-regexp-pt)
        (if (equal word (match-string-no-properties 0))
            (replace-match (format "%s %s" word in-word)))
        (forward-line 1)))))

(defun wlist-hamming-dist-word-list (word dist)
  "Looks for the words with hamming DIST of word WORD; returns all of the in a list."
  (setq wlist-word-link nil)
  (with-current-buffer (current-buffer) 
    (goto-char (point-min))
    (save-excursion  
      (while (< (line-number-at-pos) (line-number-at-pos (point-max)))
        (looking-at wlist-regexp-pt)
        (if (= dist (wlist-hamming-dist word (match-string-no-properties 0)))
            (push (match-string-no-properties 0) wlist-word-link))
        (forward-line 1))))
  (reverse wlist-word-link))

(defun wlist-word-link-next (word dist)
  "Returns the next link of word-link with hamming DIST of word WORD."
  (car (wlist-hamming-dist-word-list word dist)))

(defun wlist-one-word-link (word dist n)
  "Returns a word-link from WORD whit hamming distance DIST."
  (let ((word-link word)
        (new-word (wlist-word-link-next word dist)))
    (while (and new-word (<= 0 n))
      (push new-word word-link)
      (wlist-one-word-link new-word dist (- n 1)))))
            
(provide 'wlist)


1. Existe tamanho palavrão em português?.

Etiquetas/Tags: aspell, emacs, elisp

✍ Teaser for my new guitar amplifier
1/4W to 3W class a mosfet amplifier

2018/03/18-00:17:02

Here is my new class A mosfet amplifier 1/4W to 3W guitar amp.

More pics and sound samples later.

Etiquetas/Tags: DIY, guitar, amplifier

✍ WAMP - 1 W guitar amplifier
A simple two stage mosfet class a guitar amplifier

2018/03/18-00:17:02

Sounds much better than any chip amp, overdrives nicely with a booster in front of it. Sounds clean with good compression, high output impedance, can drive 8/16Ohms cabs (even 4Ohm).

Some oscilloscope pics:

Have fun!

Etiquetas/Tags: class a, mosfet, guitar, amplifier, diy

Palavras chave/keywords: página pessoal, blog

Criado/Created: NaN

Última actualização/Last updated: 17-06-2018 [15:34]


Voltar à página inicial.


GNU/Emacs Creative Commons License

(c) Tiago Charters de Azevedo