dijous, 7 d’agost del 2014

Convertir un pdf en un llibre imprimible en A5 en GNU-Linux

Faig una petita pausa en les publicacions sobre arduino per comentar una sèrie de comandes que he fet servir força últimament.

Introducció

Fa poc, he tingut la necessitat d'imprimir alguns pdf Din-A4 en format de plec per tal de generar un dossier. Això, bàsicament, significa generar un nou pdf que, en imprimir-se a doble cara (pel cantó curt), genera un conjunt de full que si es dobleguen pel mig formen un dossier que es pot llegir com si d'un llibre (o llibreta) es tractés.

Per exemple, si tenim un pdf amb 4 fulls i imprimim a dos fulls per cara i doble cara, les pàgines ens quedaran impreses amb el següent ordre:

[1] [2] | [3] [4]

En canvi, si es converteix a plec, les pàgines queden ordenades de la següent manera:

[4] [1] | [2] [3]

D'aquesta manera, al doblegar el full en quedarà visible la pàgina [1] i, en obrir-la, tindrem la [2] a la esquerra i la [3] a la dreta per, finalment, arribar a la [4] en tancar el dossier.

Algunes impressores venen de base amb la possibilitat de fer plecs, però no es molt comú. Per un altre costat, quan estem imprimint moltes pàgines, un sol plec seria massa gruixut i es més convenient separar-ho en més d'un.  Òbviament, això implica enquadernar-ho després per unir els plecs, però això és un altre tema.

Gràcies a les eines pstools de GNU-Linux és relativament senzill d'aconseguir. Després de mirar un parell de guies (SonsoTux i La Espiral) he arribat a un shell script que fa justament això.

Arxiu .sh

 A continuació poso el codi i comento després com es fa servir (codi formatejat amb http://hilite.me/):


#!/bin/bash
if [ $# -eq 0 ]
 then
    echo "Sintaxis: $0 <arxiu pdf origen> [arxiu pdf desti] [nombre de fulls per plec]"
    exit
fi
echo "Convertint $1"
rm /tmp/duplex.ps
rm /tmp/duplex_a5.ps
pdftops $1 /tmp/duplex.ps
if [ $# -eq 3 ]
 then
    echo "plecs de $3 fulls"
    pags=$(($3*4))
    psbook -s$pags /tmp/duplex.ps | psnup -pa4 -2 > /tmp/duplex_a5.ps
 else
    psbook /tmp/duplex.ps | psnup -pa4 -2 > /tmp/duplex_a5.ps
fi
if [ $# -gt 1 ]
  then
    a=$2
else
    a=duplex_$1
fi
echo "El nou arxiu es diu $a"
ps2pdf /tmp/duplex_a5.ps $a
rm /tmp/duplex.ps
rm /tmp/duplex_a5.ps

El següent codi es pot guardar en un arxiu ".sh" per executar-lo en qualsevol moment.

Com fer-lo servir

Suposant que el guardem en un arxiu anomenat "plec.sh" per cridar-lo podem fer-ho de tres maneres:


./plec.sh arxiu_origen.pdf

Aquesta crida generarà un document anomenat "duplex_arxiu_origen.pdf" a punt per ser imprès en un únic plec. Alternativament també podem fer:


./plec.sh arxiu_origen.pdf arxiu_desti.pdf

Aquesta comanda és idèntica a l'anterior, però l'arxiu resultant es dirà "arxiu_desti.pdf". Finalment:


./plec.sh arxiu_origen.pdf arxiu_desti.pdf 8

Amb aquesta comanda no només generarem un arxiu anomenat "arxiu_desti.pdf", sinó que aquesta estarà preparat per imprimir-se en plecs de 8 fulls cadascún.

Breu explicació del funcionament

No entraré en  masses detalls. A nivell bàsic, la comanda fa els següents passos:
  1. Convertir el pdf original en un arxiu ps temporal (comanda "pdftops")
  2. Amb la comanda "psbook" reordena les pàgines en plecs (les pàgines per plec es determina amb el paràmetre "-s", si no s'especifica fa un únic plec)
  3. Un cop reordenat, la comanda "psnup -pa4 -2" converteix el pdf Din-A4 en un pdf amb dues pàgines Din-A5 per cara.
  4. Convertir el ps resultant en el pdf final (comanda "ps2pdf")

dilluns, 7 de juliol del 2014

8bit pseudo-theremin (4): afegir un led bicolor per indicar el tempo

A l'article anterior vaig afegir un potenciòmetre per indicar el tempo. El problema és que no hi havia cap indicador visual del tempo actual. Per aquest motiu he decidit afegir un led de dos colors per indicar-ho.

Esquema del circuit

El codi no canvia gaire, a nivell bàsic s'ha afegit un vector amb dos pins (led vermell, led verd) i es va activant o desactivant depenent del cicle on s'estigui.


/*
 Translate HC-SR04 Ping distance sensor into buzzer tone with a potentiometer tempo
 
 Author: Ferran Recio
 This code is part of the project 8bit pseudo-theremin (http://laveudet.blogspot.com.es/2014/07/pseudo-theremin-8bits-part-0.html)
 
 Code based on:
 
 HC-SR04 Ping distance code by ScottC here: http://arduinobasics.blogspot.com.au/2012/11/arduinobasics-hc-sr04-ultrasonic-sensor.html
 buzzer tutorial here:  http://arduino.cc/en/Tutorial/Tone
 
 on 04 Jul 2014.
 */

#define echoPin 7 // Echo Pin
#define trigPin 8 // Trigger Pin
#define LEDPin 13 // Onboard LED
 
int potenPid = A1;

int buzzerPin = 10;
int buzztone = 0;

//buzzer tone range
int maxbuzztone = 2500;//4978;
int minbuzztone = 1;

int maximumRange = 30; // Maximum range needed
int minimumRange = 1; // Minimum range needed
long duration, distance; // Duration used to calculate distance

//marcador de tempo
int tempo[] = {2,3};//leds
int currled = 0;

int delayval = 25;


void setup() {
  Serial.begin (9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(LEDPin, OUTPUT); // Use LED indicator (if required)
  pinMode(buzzerPin, OUTPUT);   // sets the pin as output
  
  int i;
  for (i = 0; i < 2; i = i + 1) {
    pinMode(tempo[i], OUTPUT);
  }
  
}

void loop() {
  /* The following trigPin/echoPin cycle is used to determine the
   distance of the nearest object by bouncing soundwaves off of it. */ 
   digitalWrite(trigPin, LOW); 
   delayMicroseconds(2);
  
   digitalWrite(trigPin, HIGH);
   delayMicroseconds(10); 
   
   digitalWrite(trigPin, LOW);
   duration = pulseIn(echoPin, HIGH);
   
   //Calculate the distance (in cm) based on the speed of sound.
   distance = duration/58.2;
   
   if (distance >= maximumRange || distance <= minimumRange){
     //Serial.println("-1");
     digitalWrite(LEDPin, LOW);
     noTone(buzzerPin);
   }
   else {
     digitalWrite(LEDPin, HIGH);
     
     buzztone = map(distance, minimumRange, maximumRange, minbuzztone, maxbuzztone);
     buzztone = maxbuzztone - buzztone;
     
     tone(buzzerPin,buzztone);
   }
   
   //tempo
   if (currled==0) {
    currled = 1;
    digitalWrite(tempo[0], HIGH);
    digitalWrite(tempo[1], LOW);
   } else {
    currled = 0;
    digitalWrite(tempo[0], LOW);
    digitalWrite(tempo[1], HIGH);
   }

   
   //pillem el delay
   delayval = analogRead(potenPid);
   delay(delayval+1);
}

Aquest el vídeo de l'efecte:


divendres, 4 de juliol del 2014

8bit pseudo-theremin (3): afegir un potenciometre per marcar el tempo

El primer pas del 8bit Theremin convertia la distancia en notes del brunzidor. Tot i això, el so era força molest perquè arribava a notes molt agudes i perquè l'espera entre notes era de només 25 milisegons.

El següent pas és afegir un potenciòmetre per tal d'indicar l'espera entre tons. O sigui, el tempo.

Esquema del cablejat

En aquest cas, el codi recull el valor del potenciòmetre i el fa servir de cara a l'espera entre execucions de la funció loop. A més, s'han polit els distàncies i el rang de tons del brunzidor.


/*
 Translate HC-SR04 Ping distance sensor into buzzer tone with a potentiometer tempo
 
 Author: Ferran Recio
 This code is part of the project 8bit pseudo-theremin (http://laveudet.blogspot.com.es/2014/07/pseudo-theremin-8bits-part-0.html)
 
 Code based on:
 
 HC-SR04 Ping distance code by ScottC here: http://arduinobasics.blogspot.com.au/2012/11/arduinobasics-hc-sr04-ultrasonic-sensor.html
 buzzer tutorial here:  http://arduino.cc/en/Tutorial/Tone
 
 on 04 Jul 2014.
 */

#define echoPin 7 // Echo Pin
#define trigPin 8 // Trigger Pin
#define LEDPin 13 // Onboard LED
 
int potenPid = A1;

int buzzerPin = 10;
int buzztone = 0;

//buzzer tone range
int maxbuzztone = 2500;//4978;
int minbuzztone = 1;

int maximumRange = 30; // Maximum range needed
int minimumRange = 1; // Minimum range needed
long duration, distance; // Duration used to calculate distance

int delayval = 25;


void setup() {
  Serial.begin (9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(LEDPin, OUTPUT); // Use LED indicator (if required)
  pinMode(buzzerPin, OUTPUT);   // sets the pin as output
  
}

void loop() {
  /* The following trigPin/echoPin cycle is used to determine the
   distance of the nearest object by bouncing soundwaves off of it. */ 
   digitalWrite(trigPin, LOW); 
   delayMicroseconds(2);
  
   digitalWrite(trigPin, HIGH);
   delayMicroseconds(10); 
   
   digitalWrite(trigPin, LOW);
   duration = pulseIn(echoPin, HIGH);
   
   //Calculate the distance (in cm) based on the speed of sound.
   distance = duration/58.2;
   
   if (distance >= maximumRange || distance <= minimumRange){
     digitalWrite(LEDPin, LOW);
     noTone(buzzerPin);
   }
   else {
     digitalWrite(LEDPin, HIGH);
     
     buzztone = map(distance, minimumRange, maximumRange, minbuzztone, maxbuzztone);
     buzztone = maxbuzztone - buzztone;
     
     tone(buzzerPin,buzztone);
   }

   
   //pillem el delay
   delayval = analogRead(potenPid);
   delay(delayval+1);
}

A continuació poso un vídeo de com funciona: