mercoledì 2 agosto 2017

Clone cinese Lilypad

Per un progettino "indossabile" mi sono deciso a comprarmi una Arduino Lilypad...il problema e' come al solito che l'originale costa un botto e ci sono alternative piu' economiche


Il problema, come si vede chiaramente dal video sottostante, e' che il dispositivo, seppur funzionante, non e' una su basetta flessibile ma e' semplicemente un PCB rigido tagliato di forma rotonda (ascoltare l'audio dell'impatto sul tavolo)


la vera Lilypad fa questo


in buona sostanza da non ricomprare ed una stella su Amazon

Kotlin su Android Studio 2

Come aggiungere il supporto a Kotlin in Android Studio 2

Per prima cosa da File/Preferences si cercano i plugin e si installa JetBrains Plugin. Fatto cio' appare nella colonna di destra il plugin di Kotlin da poter installare


Fatto cio', per convertire un progetto Android/Java in Android/Kotlin, si crea un normale progetto, successivamente con la combinazione cmd+shift+A (in Mac) si cerca Convert Java File to Kotlin

L'IDE a questa punto richiede di risincronizzare il progetto



ed il codice Java viene convertito in Kotlin. Al monte di compilare viene anche chiesto di aggiornare gradle
il codice di un semplice esempio che cambia la stringa di una textview e' il seguente

package innocenti.luca.com.kot_test

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val testo: TextView = findViewById(R.id.textView) as TextView;
        testo.setText("Luca");

    }
}


martedì 1 agosto 2017

TI PS-6200 32Kb

Ogni tanto i cestini della spazzatura continuano a regalare soddisfazioni agli amanti di hardware obsoleto. E' oggi il caso di un Texas Instruments PS-6200 con 32 Kb di memoria.
Si tratta di un organizer (agenda, todo, calcolatrice, orologio, memo) del 1991 (e' una prima serie, si riconosce dalla posizione del logo sopra il display) e monta un processore derivato da Z80 (anche se ovviamente non ha una modalita' programmazione essendo una agenda elettronica e non una calcolatrice)

Il splendide condizioni di conservazione una volta inserite le batterie (due CR-2025) e' tornata a funzionare senza problemi







giovedì 27 luglio 2017

FFT su Arduino

Usando sempre come input il microfono amplificato ho provato la libreria ArduinoFFT ed in particolare l'esempio FFT_03 modificando il numero di samples a 128 e la frequenza di campionamento a 9600


--------
/*

Example of use of the FFT libray to compute FFT for a signal sampled through the ADC.
        Copyright (C) 2017 Enrique Condes

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 of the License, 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, see <http://www.gnu.org/licenses/>.

*/

#include "arduinoFFT.h"

arduinoFFT FFT = arduinoFFT(); /* Create FFT object */
/*
These values can be changed in order to evaluate the functions
*/
#define CHANNEL A0
const uint16_t samples = 128; //This value MUST ALWAYS be a power of 2
double samplingFrequency = 9600;

unsigned int delayTime = 0;

/*
These are the input and output vectors
Input vectors receive computed results from FFT
*/
double vReal[samples];
double vImag[samples];

#define SCL_INDEX 0x00
#define SCL_TIME 0x01
#define SCL_FREQUENCY 0x02

void setup()
{
  if(samplingFrequency<=1000)
    delayTime = 1000/samplingFrequency;
  else
    delayTime = 1000000/samplingFrequency;
  Serial.begin(115200);
  Serial.println("Ready");
}

void loop()
{
  for(uint16_t i =0;i<samples;i++)
  {
    vReal[i] = double(analogRead(CHANNEL));
    if(samplingFrequency<=1000)
      delay(delayTime);
    else
      delayMicroseconds(delayTime);
  }
  /* Print the results of the sampling according to time */
  Serial.println("Data:");
  PrintVector(vReal, samples, SCL_TIME);
  FFT.Windowing(vReal, samples, FFT_WIN_TYP_HAMMING, FFT_FORWARD); /* Weigh data */
  Serial.println("Weighed data:");
  PrintVector(vReal, samples, SCL_TIME);
  FFT.Compute(vReal, vImag, samples, FFT_FORWARD); /* Compute FFT */
  Serial.println("Computed Real values:");
  PrintVector(vReal, samples, SCL_INDEX);
  Serial.println("Computed Imaginary values:");
  PrintVector(vImag, samples, SCL_INDEX);
  FFT.ComplexToMagnitude(vReal, vImag, samples); /* Compute magnitudes */
  Serial.println("Computed magnitudes:");
  PrintVector(vReal, (samples >> 1), SCL_FREQUENCY);
  double x = FFT.MajorPeak(vReal, samples, samplingFrequency);
  Serial.println(x, 6);
  while(1); /* Run Once */

}

void PrintVector(double *vData, uint8_t bufferSize, uint8_t scaleType)
{
  for (uint16_t i = 0; i < bufferSize; i++)
  {
    double abscissa;
    /* Print abscissa value */
    switch (scaleType)
    {
      case SCL_INDEX:
        abscissa = (i * 1.0);
break;
      case SCL_TIME:
        abscissa = ((i * 1.0) / samplingFrequency);
break;
      case SCL_FREQUENCY:
        abscissa = ((i * 1.0 * samplingFrequency) / samples);
break;
    }
    Serial.print(abscissa, 6);
    Serial.print(" ");
    Serial.print(vData[i], 4);
    Serial.println();
  }
  Serial.println();
}
--------

Valori piu' grandi di 128 nel numero di samples generano un errore di out_of_memory

Suonando su una tastiera musicale la quinta ottava ho acquisito i dati e trascitto il valore di massimo picco



Come si vede i valori di frequenza calcolati sono molto differenti da quelli teorici ma si osservi che il rapporto di frequenza tra due note consecutive distante due semitoni e' molto prossimo al valore teorico di 1.1225. Inoltre il rapporto tra la frequenza teorica e quella calcolata e' sempre di circa 2.1 quindi puo' trattarsi della prima armonica superiore

Eseguendo la stessa prova ma sulla 4° ottava i risultati sono i seguenti


Con questo sketch le classi di frequenza hanno una larghezza di 75 Hz...quindi non e' comunque un sistema da usare come accordatore

In generale e' comunque un sistema che funziona bene nell'ambito delle frequenze udibili

martedì 25 luglio 2017

FHT su Arduino

Un bel po' di tempo fa avevo provato ad accoppiare un microfono ad Arduino ma i risultati non mi avevano entusiasmato...visto che volevo provare ad usare FFT su Arduino ho ritirato fuori il vecchio modulo e lo ho accoppiato alla libreria ArduinoFHT di Open Music Lab

Lo sketch Arduino e' interessante perche' non si tratta di leggere solo l'input A0 ma inserisce un bel po' di trucchetti come mandare l'ADC in modalita' free running per velocizzare al massimo il campionamento

-----------------------
/*
fht_adc.pde
guest openmusiclabs.com 9.5.12
example sketch for testing the fht library.
it takes in data on ADC0 (Analog0) and processes them
with the fht. the data is sent out over the serial
port at 115.2kb.  there is a pure data patch for
visualizing the data.
*/

#define LOG_OUT 1 // use the log output function
#define FHT_N 256 // set to 256 point fht

#include <FHT.h> // include the library

void setup() {
  Serial.begin(115200); // use the serial port
  TIMSK0 = 0; // turn off timer0 for lower jitter
  ADCSRA = 0xe5; // set the adc to free running mode
  ADMUX = 0x40; // use adc0
  DIDR0 = 0x01; // turn off the digital input for adc0
}

void loop() {
  while(1) { // reduces jitter
    cli();  // UDRE interrupt slows this way down on arduino1.0
    for (int i = 0 ; i < FHT_N ; i++) { // save 256 samples
      while(!(ADCSRA & 0x10)); // wait for adc to be ready
      ADCSRA = 0xf5; // restart adc
      byte m = ADCL; // fetch adc data
      byte j = ADCH;
      int k = (j << 8) | m; // form into an int
      k -= 0x0200; // form into a signed int
      k <<= 6; // form into a 16b signed int
      fht_input[i] = k; // put real data into bins
    }
    fht_window(); // window the data for better frequency response
    fht_reorder(); // reorder the data before doing the fht
    fht_run(); // process the data in the fht
    fht_mag_log(); // take the output of the fht
    sei();
    Serial.write(255); // send a start byte
    Serial.write(fht_log_out, FHT_N/2); // send out the data
  }
}
-----------------------
ci sono diversi tipi di rappresentazione del risultati (nell'esempio viene indicata la rappresentazione logaritmica).
La rappresentazione del formato di output e' descritta qui. In pratica nel caso in esempio sono sequenze di 256 byte in cui ciascuno rappresenta una suddivisione dello spettro di frequenze
Per calcolare quanto e' ampio un intervallo si deve conoscere il passo di campionamento secondo la regola
  • Frequency(k) = (k)*(sample_rate)/(FHT_N)
Per modificare il passo di campionamento e' sufficiente lavorare sul valore di prescaler del convertitore analogico digitale
Di default il prescaler di ADC e' impostato a 128 il che porta ad un passo di campionamento di 9600 Hz (16.000 Hz/ 128 ovvero prescaler diviso di nuovo per 13 cicli processore per fare la conversione ADC)..in queste condizioni la massima frequenza analizzabile per il teorema di Nyiquist e' di 4800 KHz (il che va bene per suoni musicali)

In condizioni standard quindi ogni divisioni in frequenza e' larga 9600/256 =37.5Hz). Nel caso in esempio pero' tale valore e' modificato ed e' pari a 5 (gli ultimi 3 bit del valore esadecimale E5). Per variare il prescaler si deve agire sul registro ADCSRA
In pratica

#define CLOCK_PRESCALER_1 (0x0)
#define CLOCK_PRESCALER_2 (0x1)
#define CLOCK_PRESCALER_4 (0x2)
#define CLOCK_PRESCALER_8 (0x3)
#define CLOCK_PRESCALER_16 (0x4)
#define CLOCK_PRESCALER_32 (0x5)
#define CLOCK_PRESCALER_64 (0x6)
#define CLOCK_PRESCALER_128 (0x7)
#define CLOCK_PRESCALER_256 (0x8)


I dati che vengono inviati sulla porta seriale sono di tipo binario ed e' quindi necessario un programma per leggerli. Ho quindi installato Pure Data Extended e carico lo script di esempio arduinofft_display. Una volta settata la giusta porta seriale si vede il grafico popolarsi con i dati derivanti dalla Arduino



Sono stati suonati su una tastiera 3 Do a diversa altezza

NB: e' interessante leggere il codice sorgente di FHT.h perche' il codice e' quasi in tutto in ASM per ATMEGA

venerdì 21 luglio 2017

Force resistive sensor FSR402 ed Arduino

Un sensore comodo, anche se abbastanza costoso, da accoppiare ad un Arduino sono le resistenze variabile in funzione della pressione (Force-sensitive resistor o FSR)

In pratica premendo con qualche forza di pochi grammi al centro del sensore la resistenza varia fino ad annullarsi (in generale essendo funzione della pressione maggiore e' l'area interessata a parita' di pressione e maggiore sara' la risposte). E' quindi possibile sfruttare questo comportamento per creare un partitore di tensione
e misurare i dati in un ingresso analogico di Arduino
Nell'immagine sottostante uno schema base con una resistenza da 10 KOhm




Come riportata da questo sito in pratica ci sono due superfici separate da un sottile strato d'aria. Premendo si crea il contatto tra la superficie superiore e quella inferiore

Per il miglior funzionamento il sensore deve essere posto su una base liscia e piana

In generale non puo' essere usato per misurare l'intensita' di pressione (per questo esistono gli strain gauge) ma solo come una sorta di interruttore a pressione

giovedì 20 luglio 2017

GNSS raw data in Android N

Con Android N sono disponibili le API per accedere ai dati raw del GPS e comtemporaneamente e' stato rilasciato un programma di esempio GNSSLogger sia in formato sorgente che in apk



I dati che si possono registrare sono molto interessanti perche' riguardano sia lo pseudorange che le informazioni di fase permettendo quindi un posizionamento GPS estremamente preciso.

Il problema e' attualmente principalmente legato all'hardware. Sono pochi attualmente i dispositivi che hanno una antenna GPS atta a registrare tutte le informazioni

Per esempio (vedi questo link) il Nexus 5x e' un pessimo candidato mentre e' decisamente piu' appetibile il Nexus 9 (parlando dei dispositivi che uso)





Per elaborare il file dati in uscita da GNSSLogger Google mette a disposizione degli script Matlab ma non possedendo una licenza ho trovato preferibile usare uno script in Python di Lukasz Bonenberg’s all'indirizzo 
https://github.com/DfAC/AndroidGNSS

Per fare girare lo script ipynb (iPython notebook) ho dovuto smanettare sulla mia Debian Box perche' e' stato necessario installare jupyter

pip install jupyter 

e poi sono state aggiornate alcune librerie mediante pip --upgrade

pip install --upgrade scipy


(si fa la stessa cosa con le librerie pandas, seaborn, numpy e matplotlib)

finiti gli aggiornamenti delle librerie si lancia

jupyter notebook --allow-root 

e si apre il file ProcessRanges.ipynb modificando il nome del file alla riga data_file e, dal menu, si lancia Cell/Run All



e si ottengono i dati delle elaborazioni. Nel caso del Nexus 5x lo script genera un errore quasi subito nel popolare un array mentre con i dati di Nexus 9 (grafici sottostanti) l'elaborazione si sviluppa fino a quando si cerca di elaborare la costellazione Galileo (non presente sul sensore del Nexus 9)









Debugger integrato ESP32S3

Aggiornamento In realta' il Jtag USB funziona anche sui moduli cinesi Il problema risiede  nell'ID USB della porta Jtag. Nel modulo...