Radio 3.0 – la radio qui tweet. Christopher Santerre
Le Fablab de l’ensci, un terrain d’expérimentation
Radio 3.0 est un objet qui permet de sélectionner, d’écouter et de partager des données liées à des flux musicaux numériques. Mélangeant usages d’hier et pratiques d’aujourd’hui il est un support de recherche sur de nouvelles interactions possibles entre les hommes, les objets et le réseau. Revendiquant une conception libre, reproductible et reprogrammable aisément, RADIO 3.0 est un patchwork fait d’éléments de la grande industrie et de pièces sur mesures. Ayant largement recours à des technologies opensource comme Arduino,RADIO 3.0 fut une opportunité d’aborder l’ensemble des dimensions d’un projet de design de l’intention de départ au prototype fonctionnel. Ce fut l’occasion de tester directement l’interface de l’objet à travers ses différents capteurs et leur programmation.
ainsi qu’un puissant outil de production
Le Fablab de l’ENSCI m’a permis d’expérimenter la conception d’un objet complexe intégrant à la fois des savoirs-faires traditionnels comme celui du bois à de l’électronique de pointe. Cela a été l’occasion de générer de nombreux ponts entre les différents ateliers de l’école que j’ai pu utiliser pendant ces quelques mois comme un outil de prototypage et de production poussé.
Plans:
Liste des éléments composant la radio:
1x afficheur Sure Electronics matrice led rouge 32×8
1x ampli mono velleman 7w
1x hauts parleurs VISATON FRWS5 2watts
1x Potentiomètre linéaire simple
1x Rotary encoder
1x Inverseur électronique
code arduino (provisoire)
#include <avr/pgmspace.h>
enum PinAssignments { encoderPinA = 2, encoderPinB = 3,};
// chris config#define CS1 13 #define CLK 10 // WR clock#define RD 5 #define DAT 7///*// uros config #define CS1 13 #define CLK 4 // WR clock #define RD 5 #define DAT 7*/#define RC_MASTER_MODE 0b100000110000#define SYS_DIS 0b100000000000#define SYS_EN 0b100000000010#define LED_OFF 0b100000000100#define LED_ON 0b100000000110#define N_MOS_COM8 0b100001000000#define PWM_16 0b100101011110#define PWM_1 0b100101000000#define CS_ON digitalWrite(CS1, LOW)#define CS_OFF digitalWrite(CS1, HIGH)#define CLK_ON digitalWrite(CLK, HIGH)#define CLK_OFF digitalWrite(CLK, LOW)#define DAT_ON digitalWrite(DAT, HIGH)#define DAT_OFF digitalWrite(DAT, LOW)
#define WORLD 0#define LOCAL 1
#define RESISTOR 0
#define TWEET 9
#define SWITCH 8
#define W_MATRIX 32#define H_MATRIX 8
byte image[32];byte p_image[32];boolean refreshImg = true;
boolean etat = false;int count = 0;
///encodeur
volatile unsigned int encoderPos = 0;unsigned int lastReportedPos = 1;
boolean A_set = false;boolean B_set = false;
long timerEnc = 0;int encoder = 0;
///end encodeur
boolean uglySwitch = false; // bug correction, change this auful thing
byte ser = 0;
long timer = 0;
boolean lock = false;
char* phrases[] = {
« Eclectik – Pierric Bailly », « La Tete au Carre – Les comites d’ethique », « PLACE DE LA TOILE 01.05.2011 », « Rencontre des Ateliers – Gilles Rougon », « Le Mouv – Le Post Politik 13.06.2011 », // « CHIC – Le Freak », « Frederic Chopin – Minute Waltz », « Herbie Hancock – Cantaloupe Island »}; /// world 5-7
int local = 5;int world = 0;
String incoming = « »;
const byte ascii[][6] PROGMEM = { // put this into the flash memory 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 32 (space)
0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, // 33 !
0x00, 0x07, 0x00, 0x07, 0x00, 0x00, // 34 »
0x14, 0x7F, 0x14, 0x7F, 0x14, 0x00, // 35 #
0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x00, // 36 0x
0x23, 0x13, 0x08, 0x64, 0x62, 0x00, // 37 %
0x36, 0x49, 0x56, 0x20, 0x50, 0x00, // 38 &
0x00, 0x08, 0x07, 0x03, 0x00, 0x00, // 39 ‘
0x00, 0x1C, 0x22, 0x41, 0x00, 0x00, // 40 (
0x00, 0x41, 0x22, 0x1C, 0x00, 0x00, // 41 )
0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 0x00, // 42 *
0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, // 43 +
0x00, 0x80, 0x70, 0x30, 0x00, 0x00, // 44 ,
0x08, 0x08, 0x08, 0x08, 0x08, 0x00, // 45 –
0x00, 0x00, 0x60, 0x60, 0x00, 0x00, // 46 .
0x20, 0x10, 0x08, 0x04, 0x02, 0x00, // 47 /
0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, // 48 0
0x00, 0x42, 0x7F, 0x40, 0x00, 0x00, // 49 1
0x72, 0x49, 0x49, 0x49, 0x46, 0x00, // 50 2
0x21, 0x41, 0x49, 0x4D, 0x33, 0x00, // 51 3
0x18, 0x14, 0x12, 0x7F, 0x10, 0x00, // 52 4
0x27, 0x45, 0x45, 0x45, 0x39, 0x00, // 53 5
0x3C, 0x4A, 0x49, 0x49, 0x31, 0x00, // 54 6
0x41, 0x21, 0x11, 0x09, 0x07, 0x00, // 55 7
0x36, 0x49, 0x49, 0x49, 0x36, 0x00, // 56 8
0x46, 0x49, 0x49, 0x29, 0x1E, 0x00, // 57 9
0x00, 0x00, 0x14, 0x00, 0x00, 0x00, // 58 :
0x00, 0x40, 0x34, 0x00, 0x00, 0x00, // 59 ;
0x00, 0x08, 0x14, 0x22, 0x41, 0x00, // 60 <
0x14, 0x14, 0x14, 0x14, 0x14, 0x00, // 61 =
0x00, 0x41, 0x22, 0x14, 0x08, 0x00, // 62 >
0x02, 0x01, 0x59, 0x09, 0x06, 0x00, // 63 ?
0x3E, 0x41, 0x5D, 0x59, 0x4E, 0x00, // 64 @
0x7C, 0x12, 0x11, 0x12, 0x7C, 0x00, // 65 A
0x7F, 0x49, 0x49, 0x49, 0x36, 0x00, // 66 B
0x3E, 0x41, 0x41, 0x41, 0x22, 0x00, // 67 C
0x7F, 0x41, 0x41, 0x41, 0x3E, 0x00, // 68 D
0x7F, 0x49, 0x49, 0x49, 0x41, 0x00, // 69 E
0x7F, 0x09, 0x09, 0x09, 0x01, 0x00, // 70 F
0x3E, 0x41, 0x41, 0x51, 0x73, 0x00, // 71 G
0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00, // 72 H
0x00, 0x41, 0x7F, 0x41, 0x00, 0x00, // 73 I
0x20, 0x40, 0x41, 0x3F, 0x01, 0x00, // 74 J
0x7F, 0x08, 0x14, 0x22, 0x41, 0x00, // 75 K
0x7F, 0x40, 0x40, 0x40, 0x40, 0x00, // 76 L
0x7F, 0x02, 0x1C, 0x02, 0x7F, 0x00, // 77 M
0x7F, 0x04, 0x08, 0x10, 0x7F, 0x00, // 78 N
0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00, // 79 O
0x7F, 0x09, 0x09, 0x09, 0x06, 0x00, // 80 P
0x3E, 0x41, 0x51, 0x21, 0x5E, 0x00, // 81 Q
0x7F, 0x09, 0x19, 0x29, 0x46, 0x00, // 82 R
0x26, 0x49, 0x49, 0x49, 0x32, 0x00, // 83 S
0x03, 0x01, 0x7F, 0x01, 0x03, 0x00, // 84 T
0x3F, 0x40, 0x40, 0x40, 0x3F, 0x00, // 85 U
0x1F, 0x20, 0x40, 0x20, 0x1F, 0x00, // 86 V
0x3F, 0x40, 0x38, 0x40, 0x3F, 0x00, // 87 W
0x63, 0x14, 0x08, 0x14, 0x63, 0x00, // 88 X
0x03, 0x04, 0x78, 0x04, 0x03, 0x00, // 89 Y
0x61, 0x59, 0x49, 0x4D, 0x43, 0x00, // 90 Z
0x00, 0x7F, 0x41, 0x41, 0x41, 0x00, // 91
0x02, 0x04, 0x08, 0x10, 0x20, 0x00, // 92
0x00, 0x41, 0x41, 0x41, 0x7F, 0x00, // 93
0x04, 0x02, 0x01, 0x02, 0x04, 0x00, // 94
0x40, 0x40, 0x40, 0x40, 0x40, 0x00, // 95
0x00, 0x03, 0x07, 0x08, 0x00, 0x00, // 96
0x20, 0x54, 0x54, 0x78, 0x40, 0x00, // 97 a
0x7F, 0x28, 0x44, 0x44, 0x38, 0x00, // 98 b
0x38, 0x44, 0x44, 0x44, 0x28, 0x00, // 99 c
0x38, 0x44, 0x44, 0x28, 0x7F, 0x00, // 100 d
0x38, 0x54, 0x54, 0x54, 0x18, 0x00, // 101 e
0x00, 0x08, 0x7E, 0x09, 0x02, 0x00, // 102 f
0x18, 0xA4, 0xA4, 0x9C, 0x78, 0x00, // 103 g
0x7F, 0x08, 0x04, 0x04, 0x78, 0x00, // 104 h
0x00, 0x44, 0x7D, 0x40, 0x00, 0x00, // 105 i
0x20, 0x40, 0x40, 0x3D, 0x00, 0x00, // 106 j
0x7F, 0x10, 0x28, 0x44, 0x00, 0x00, // 107 k
0x00, 0x41, 0x7F, 0x40, 0x00, 0x00, // 108 l
0x7C, 0x04, 0x78, 0x04, 0x78, 0x00, // 109 m
0x7C, 0x08, 0x04, 0x04, 0x78, 0x00, // 110 n
0x38, 0x44, 0x44, 0x44, 0x38, 0x00, // 111 o
0xFC, 0x18, 0x24, 0x24, 0x18, 0x00, // 112 p
0x18, 0x24, 0x24, 0x18, 0xFC, 0x00, // 113 q
0x7C, 0x08, 0x04, 0x04, 0x08, 0x00, // 114 r
0x48, 0x54, 0x54, 0x54, 0x24, 0x00, // 115 s
0x04, 0x04, 0x3F, 0x44, 0x24, 0x00, // 116 t
0x3C, 0x40, 0x40, 0x20, 0x7C, 0x00, // 117 u
0x1C, 0x20, 0x40, 0x20, 0x1C, 0x00, // 118 v
0x3C, 0x40, 0x30, 0x40, 0x3C, 0x00, // 119 w
0x44, 0x28, 0x10, 0x28, 0x44, 0x00, // 120 x
0x4C, 0x90, 0x90, 0x90, 0x7C, 0x00, // 121 y
0x44, 0x64, 0x54, 0x4C, 0x44, 0x00, // 122 z
0x00, 0x08, 0x36, 0x41, 0x00, 0x00, // 123
0x00, 0x00, 0x77, 0x00, 0x00, 0x00, // 124
0x00, 0x41, 0x36, 0x08, 0x00, 0x00, // 125
0x02, 0x01, 0x02, 0x04, 0x02, 0x00, // 126
0x3C, 0x26, 0x23, 0x26, 0x3C, 0x00 }; // 127
void setup() {
pinMode(CS1, OUTPUT); pinMode(CLK, OUTPUT); pinMode(RD, OUTPUT); pinMode(DAT, OUTPUT);
commandWrite(SYS_EN); commandWrite(LED_ON); commandWrite(RC_MASTER_MODE); commandWrite(N_MOS_COM8); commandWrite(PWM_16);
initImage(); for (int i=0; i<32; i++) p_image[i] = 0;
/// Serial.begin(9600);
/// SWITCH pinMode(SWITCH, INPUT); digitalWrite(SWITCH, HIGH); // pull down
pinMode(TWEET, INPUT);
timer = millis();
//for (int i=0; i<5; i++) Serial.println(getLength(phrases[i]));
if (getWorldLocalSwitch() == WORLD) { Serial.println(world); } else { Serial.println(local); }
///encodeur pinMode(encoderPinA, INPUT); pinMode(encoderPinB, INPUT);
digitalWrite(encoderPinA, HIGH); // turn on pullup resistor digitalWrite(encoderPinB, HIGH); // turn on pullup resistor
// encoder pin on interrupt 0 (pin 2) attachInterrupt(0, doEncoderA, CHANGE); // encoder pin on interrupt 1 (pin 3) attachInterrupt(1, doEncoderB, CHANGE);
////
}
void loop() { // this is main loop for drawing
events();
/* Serial.print(world); Serial.print( » « ); Serial.println(local); */
if (millis()>timer + 70){ //// makeScene(); draw(); //// timer = millis(); }
}
void makeScene() { background(0); // phrase scrolling count–;
if (getWorldLocalSwitch() == WORLD) { // Serial.println(getLength(phrases[world]));
if (count==-(getLength(phrases[world])*6)) count = W_MATRIX;
drawPhrase(phrases[world],count,0);
} else {
if (count==-(getLength(phrases[local])*6)) count = W_MATRIX;
drawPhrase(phrases[local],count,0); }
}
void draw() { // don’t touch here
CS_ON; addressWrite(0x00); for (int i=0; i<32; i++) { byteOut(image[i]); } CS_OFF;
}
int getLength(String s) { return s.length();}
void events() {
///SWITCH static int lastWorldChange = 0; int wlc = getWorldLocalSwitch(); if (lastWorldChange != wlc) { worldLocalChange(); uglySwitch = false; }
lastWorldChange = wlc; ///END SWITCH
//// encodeur
if (lastReportedPos != encoderPos) {
/* Serial.print(« Index: »); Serial.print(encoderPos, DEC); Serial.println(); */
if (millis() > timerEnc+600) {
if (lastReportedPos>encoderPos) { encoder = 1; listChange(); } else { encoder = 2; listChange(); }
}
timerEnc = millis();
lastReportedPos = encoderPos; } /// end encodeur
///TWITTER static int lastTweet = 0; int tt = getTweet(); if (lastTweet != tt) tweet(); lastTweet = tt; ///END TWITTER
}
void tweet() { background(0); drawPhrase(« share », 0,0); Serial.println(8); draw(); delay(1500); count = W_MATRIX;}
void worldLocalChange() {
background(0);
if (getWorldLocalSwitch() == WORLD) {
drawPhrase(« local », 0,0); draw(); Serial.println(9); // 8- stop delay(1500); count = W_MATRIX; Serial.println(world);
} else { //// WORLD
drawPhrase(« world », 0,0); draw(); Serial.println(9); // 8- stop delay(1500); count = W_MATRIX; Serial.println(local); }
}
void listChange() {
switch(encoder) { case 1: /// turn UP
if (getWorldLocalSwitch() == WORLD) {
if (world<4) world++; else world = 0; uglySwitch = true; scrollUpPhrase(phrases[world]); Serial.println(world);
} else {
if (uglySwitch == false) { if (local<7) local++; else local = 5; } scrollUpPhrase(phrases[local]); Serial.println(local); } break;
case 2: /// turn DOWN
if (getWorldLocalSwitch() == WORLD) {
if (world>0) world–; else world = 4; scrollDownPhrase(phrases[world]); Serial.println(world); } else {
if (local>5) local–; else local = 7; scrollDownPhrase(phrases[local]); Serial.println(local); }
break; }
delay(1500); count = 0;
/* Serial.print(world); Serial.print( » « ); Serial.println(local); */
}
int getWorldLocalSwitch() { return digitalRead(SWITCH); }
int getTweet() { return digitalRead(TWEET);}
void invert() { for (int i=0; i<32; i++) { image[i] = image[i] ^ 255; }}
/*void drawImage(byte *img, int x, int y, int w, int h) { if ( ((y+h)>0) && (y<H_MATRIX) ) { // define y on screen if ( ((x+w)>0) && (x<W_MATRIX) ) { // define x on screen byte imgA[W_MATRIX]; for (int i=0; i<W_MATRIX; i++) imgA[i] = 0; //x for (int i=0; i<w-x; i++) imgA[x+i] = img[i]; //y for (int i=0; i<W_MATRIX; i++) { imgA[i] = (y>0) ? imgA[i]<<y : imgA[i]>>y; image[i] = imgA[i]; } } } } */
void scrollDownPhrase(char *p2) {
byte imgA[W_MATRIX]; for (int j=0; j<W_MATRIX; j++) imgA[j] = image[j];
for (int i=0;i<=H_MATRIX;i++) {
//y for (int j=0; j<W_MATRIX; j++) image[j] = imgA[j]<<i;
drawPhrase(p2, 0, H_MATRIX-i); draw(); delay(100); }}
void scrollUpPhrase(char *p2) {
byte imgA[W_MATRIX]; for (int j=0; j<W_MATRIX; j++) imgA[j] = image[j];
for (int i=0;i<=H_MATRIX;i++) {
//y for (int j=0; j<W_MATRIX; j++) image[j] = imgA[j]>>i;
drawPhrase(p2, 0, i-8); draw(); delay(100); }}
void drawPhrase(String phrase, int x, int y) {
int pos = x; for (int i=0; i<phrase.length(); i++) { if (pos<W_MATRIX) { drawLetterAt(phrase.charAt(i), pos, y); } else { break; } pos+=6; }
}
void drawLetterAt(char letter, int x, int y) {
if ((x<W_MATRIX) && (x>-6)) {
if ((letter>=32) && (letter<=127)) letter-=32;
byte ll[6]; ll[0] = pgm_read_byte(&(ascii[letter][0])); ll[1] = pgm_read_byte(&(ascii[letter][1])); ll[2] = pgm_read_byte(&(ascii[letter][2])); ll[3] = pgm_read_byte(&(ascii[letter][3])); ll[4] = pgm_read_byte(&(ascii[letter][4])); ll[5] = pgm_read_byte(&(ascii[letter][5])); byte *let = &ll[0];
if (x<0) { // left offscreen
////drawing on the beginning of the screen let+=abs(x); // put on the new first position for (int i=0; i<x+6; i++) { // only draw in visible area from 0 till something (x+6) if ((i+6)<W_MATRIX) {/// don’t draw in offscreen, break out
byte buff = *let++; if (y<0) { buff = buff << abs(y); } else { buff = buff >> y;
}
image[x+i] = image[x+i] | buff;
} else break; }
} else { /// drawing anywhere on the screen for (int i=0; i<6; i++) { if ((i+6)<W_MATRIX) {/// don’t draw in offscreen break out
byte buff = *let++; if (y<0) { buff = buff << abs(y);
} else { buff = buff >> abs(y);
}
image[x+i] = image[x+i] | buff;
} else break; }
} }
}
void background(int a) { // enter 1 or 0 for (int i=0; i<32; i++) { image[i] = (a>0) ? 255 : 0; }}
void initImage() { /// first image in the array// blank array for (int i=0; i<32; i++) { image[i] = 0; }}/* this function don’t use PROGMEM flash memory char *getLetter(char l) { return ascii[l-32]; } */
// Interrupt on A changing statevoid doEncoderA(){ // Test transition A_set = digitalRead(encoderPinA) == HIGH; // and adjust counter + if A leads B encoderPos += (A_set != B_set) ? +1 : -1;}
// Interrupt on B changing statevoid doEncoderB(){ // Test transition B_set = digitalRead(encoderPinB) == HIGH; // and adjust counter + if B follows A encoderPos += (A_set == B_set) ? +1 : -1;}
void byteOut(byte a) { shiftOut(DAT,CLK,LSBFIRST,a);}
void commandWrite(unsigned int command) {
unsigned char i; unsigned int j; command = command & 0x0fff; //12-bit command word, upper four bits masked CS_OFF; CS_ON;
for (i=0; i<12; i++) { CLK_OFF;
j = command & 0x0800; // return MSB command = command << 1; //Move the control character to the left one j = j >> 11; digitalWrite(DAT, j); CLK_ON; }
CS_OFF;
}
void addressWrite(unsigned char address) { unsigned char i,temp; address = address & 0x7f; CLK_OFF; DAT_ON; CLK_ON; CLK_OFF; DAT_OFF; CLK_ON; CLK_OFF; DAT_ON; CLK_ON; for(int i=0; i<7; i++) { CLK_OFF; temp = address & 0x40; address = address << 1; temp = temp >> 6; digitalWrite(DAT,temp); CLK_ON; } CLK_OFF;}
[…] Radio 3.0 – la radio qui tweet. ENSCI – FabLab […]