Differences

This shows you the differences between two versions of the page.

Link to this comparison view

pm:prj2022:arosca:senzorgaze [2022/05/27 23:10]
dumitru_razvan.dinu [Hardware Design]
pm:prj2022:arosca:senzorgaze [2022/05/29 21:37] (current)
dumitru_razvan.dinu [Software Design]
Line 5: Line 5:
  ​Proiectul prezentat are ca obiectiv inregistrarea nivelului de gaze si afisarea ​  ​Proiectul prezentat are ca obiectiv inregistrarea nivelului de gaze si afisarea ​
 acestuia pe un display led cu 4 cifre. Totodata, afisarea datelor se poate realiza si pe  acestuia pe un display led cu 4 cifre. Totodata, afisarea datelor se poate realiza si pe 
-o aplicatie mobile, prin intermediul unui modul Bluetooth, existand si o notificare prin intermediul unui buzzer in cazul in care nivelul trece de un anumit prag.+o aplicatie mobile, prin intermediul unui modul Bluetooth, existand si o notificare prin intermediul unui buzzer, ce va reda o melodie ​in cazul in care nivelul trece de un anumit prag.
  
 ===== Descriere generala ===== ===== Descriere generala =====
Line 26: Line 26:
 Schema electrica: ​ Schema electrica: ​
   ​   ​
-{{:​pm:​prj2022:​arosca:​schema_electrica-bun-ddinu.png|}}+{{:​pm:​prj2022:​arosca:​schema-el-dinuu.png|}}
 Initial mi-am dorit sa o realizez in Tinkercad, insa nu am gasit toate modulele asa ca am preferat sa realizez schema in Fritzing. Initial mi-am dorit sa o realizez in Tinkercad, insa nu am gasit toate modulele asa ca am preferat sa realizez schema in Fritzing.
-Dupa cum se poate vedea si in schema, am pus rezistente, acolo unde a fost nevoie, ​astefel ​sa nu fie pus in pericol vreo componenta.+Dupa cum se poate vedea si in schema, am pus rezistente, acolo unde a fost nevoie, ​astfel ​sa nu fie pusa in pericol vreo componenta.
  
 ===== Software Design ===== ===== Software Design =====
Line 34: Line 34:
  
 Pentru programarea placutei am folosit Arduino 1.8.19, iar schema elctrica, cum am spus si mai sus am realizat-o in Fritzing. Pentru programarea placutei am folosit Arduino 1.8.19, iar schema elctrica, cum am spus si mai sus am realizat-o in Fritzing.
 +M-am folosit si de biblioteca "​ezBuzzer.h",​ intrucat, initial, am incercat sa folosesc delay in redarea melodiilor, insa acesta, fiind blocant, imi intarzia transmiterea in aplicatie a valorii si afisarea pe display.
 Am programat Display-ul led, astfel incat sa-mi afiseze corect valorile primite. ​ Am programat Display-ul led, astfel incat sa-mi afiseze corect valorile primite. ​
-Totodata, am cosiderat numarul ​800 ca valoare de referinta pentru declansarea buzzerului, astfel, cand senzorul transmite o valoare superioara, noi vom fi notificati.+Totodata, am cosiderat numarul ​700 ca valoare de referinta pentru declansarea buzzerului, astfel, cand senzorul transmite o valoare superioara, noi vom fi notificati ​prin inceperea melodiei Merry Christmas (am presupus ca vine Craciunul mai repede pentru persoana in cauza :)).
 Aplicatia mobila am realizat-o pe platforma MIT App Inventor. Aplicatia mobila am realizat-o pe platforma MIT App Inventor.
-{{:​pm:​prj2022:​arosca:​aplicatie-cod-dinu.png|}}+ 
 +<​code>​ 
 + 
 +#include <​ezBuzzer.h>​ 
 +#define Dig1 13 
 +#define Dig2 12 
 +#define Dig3 11 
 +#define Dig4 10 
 +#define DIGIT_ON LOW 
 +#define DIGIT_OFF HIGH 
 +#define DISPLAY_BRIGHTNESS 5000 
 +boolean duiz = false; 
 +boolean hon = false; 
 +#define segA 2 
 +#define segB 3 
 +#define segC 4 
 +#define segD 5 
 +#define segE 6 
 +#define segF 7 
 +#define segG 8 
 +ezBuzzer buzzer(9);​ 
 +const int nr = A0; 
 + 
 +int melody[] = { 
 +  NOTE_C5, //1 
 +  NOTE_F5, NOTE_F5, NOTE_G5, NOTE_F5, NOTE_E5, 
 +  NOTE_D5, NOTE_D5, NOTE_D5, 
 +  NOTE_G5, NOTE_G5, NOTE_A5, NOTE_G5, NOTE_F5, 
 +  NOTE_E5, NOTE_C5, NOTE_C5, 
 +  NOTE_A5, NOTE_A5, NOTE_AS5, NOTE_A5, NOTE_G5, 
 +  NOTE_F5, NOTE_D5, NOTE_C5, NOTE_C5, 
 +  NOTE_D5, NOTE_G5, NOTE_E5, 
 +   
 +  NOTE_F5, NOTE_C5, //8  
 +  NOTE_F5, NOTE_F5, NOTE_G5, NOTE_F5, NOTE_E5, 
 +  NOTE_D5, NOTE_D5, NOTE_D5, 
 +  NOTE_G5, NOTE_G5, NOTE_A5, NOTE_G5, NOTE_F5, 
 +  NOTE_E5, NOTE_C5, NOTE_C5, 
 +  NOTE_A5, NOTE_A5, NOTE_AS5, NOTE_A5, NOTE_G5, 
 +  NOTE_F5, NOTE_D5, NOTE_C5, NOTE_C5, 
 +  NOTE_D5, NOTE_G5, NOTE_E5, 
 +  NOTE_F5, NOTE_C5, 
 + 
 +  NOTE_F5, NOTE_F5, NOTE_F5,//​17 
 +  NOTE_E5, NOTE_E5, 
 +  NOTE_F5, NOTE_E5, NOTE_D5, 
 +  NOTE_C5, NOTE_A5, 
 +  NOTE_AS5, NOTE_A5, NOTE_G5, 
 +  NOTE_C6, NOTE_C5, NOTE_C5, NOTE_C5, 
 +  NOTE_D5, NOTE_G5, NOTE_E5, 
 +  NOTE_F5, NOTE_C5,  
 +  NOTE_F5, NOTE_F5, NOTE_G5, NOTE_F5, NOTE_E5, 
 +  NOTE_D5, NOTE_D5, NOTE_D5, 
 +   
 +  NOTE_G5, NOTE_G5, NOTE_A5, NOTE_G5, NOTE_F5, //27 
 +  NOTE_E5, NOTE_C5, NOTE_C5, 
 +  NOTE_A5, NOTE_A5, NOTE_AS5, NOTE_A5, NOTE_G5, 
 +  NOTE_F5, NOTE_D5, NOTE_C5, NOTE_C5, 
 +  NOTE_D5, NOTE_G5, NOTE_E5, 
 +  NOTE_F5, NOTE_C5, 
 +  NOTE_F5, NOTE_F5, NOTE_F5, 
 +  NOTE_E5, NOTE_E5, 
 +  NOTE_F5, NOTE_E5, NOTE_D5, 
 +   
 +  NOTE_C5, NOTE_A5,//​36 
 +  NOTE_AS5, NOTE_A5, NOTE_G5, 
 +  NOTE_C6, NOTE_C5, NOTE_C5, NOTE_C5, 
 +  NOTE_D5, NOTE_G5, NOTE_E5, 
 +  NOTE_F5, NOTE_C5,  
 +  NOTE_F5, NOTE_F5, NOTE_G5, NOTE_F5, NOTE_E5, 
 +  NOTE_D5, NOTE_D5, NOTE_D5, 
 +  NOTE_G5, NOTE_G5, NOTE_A5, NOTE_G5, NOTE_F5,  
 +  NOTE_E5, NOTE_C5, NOTE_C5, 
 +   
 +  NOTE_A5, NOTE_A5, NOTE_AS5, NOTE_A5, NOTE_G5,//​45 
 +  NOTE_F5, NOTE_D5, NOTE_C5, NOTE_C5, 
 +  NOTE_D5, NOTE_G5, NOTE_E5, 
 +  NOTE_F5, NOTE_C5, 
 +  NOTE_F5, NOTE_F5, NOTE_G5, NOTE_F5, NOTE_E5, 
 +  NOTE_D5, NOTE_D5, NOTE_D5, 
 +  NOTE_G5, NOTE_G5, NOTE_A5, NOTE_G5, NOTE_F5, 
 +  NOTE_E5, NOTE_C5, NOTE_C5, 
 +   
 +  NOTE_A5, NOTE_A5, NOTE_AS5, NOTE_A5, NOTE_G5, //53 
 +  NOTE_F5, NOTE_D5, NOTE_C5, NOTE_C5, 
 +  NOTE_D5, NOTE_G5, NOTE_E5, 
 +  NOTE_F5, 0 
 +}; 
 + 
 +// note durations: 4 = quarter note, 8 = eighth note, etc, also called tempo: 
 +int noteDurations[] = { 
 +4, 
 +4, 8, 8, 8, 8, 
 +4, 4, 4, 
 +4, 8, 8 ,8, 8, 
 +4, 4, 4, 
 +4, 8, 8 ,8, 8, 
 +4, 4, 8, 8, 
 +4, 4, 4, 
 +2, 4, 
 +4, 8, 8, 8, 8, 
 +4, 4, 4, 
 +4, 8, 8, 8, 8, 
 +4, 4, 4, 
 +4, 8, 8, 8, 8, 
 +4, 4, 8, 8, 
 +4, 4, 4, 
 +2, 4, 
 +4, 4, 4, 
 +2, 4, 
 +4, 4, 4, 
 +2, 4, 
 +4, 4, 4, 
 +4, 4, 8, 8, 
 +4 , 4, 4, 
 +2, 4,  
 +4, 8, 8, 8, 8, 
 +4, 4, 4, 
 +4, 8, 8, 8, 8, 
 +4, 4, 4, 
 +4, 8, 8, 8, 8, 
 +4, 4, 8, 8,  
 +4, 4, 4, 
 +2, 4, 
 +4, 4, 4, 
 +2, 4, 
 +4, 4, 4, 
 +2, 4, 
 +4, 4, 4, 
 +4, 4, 8, 8, 
 +4, 4, 4, 
 +2, 4,  
 +4, 8, 8, 8, 8, 
 +4, 4, 4,  
 +4, 8, 8, 8, 8, 
 +4, 4, 4, 
 +4, 8, 8, 8, 8, 
 +4, 4, 8, 8,  
 +4, 4, 4,  
 +2, 4,  
 +4, 8, 8, 8, 8, 
 +4, 4, 4, 
 +4, 8, 8, 8, 8,  
 +4, 4, 4,  
 +4, 8, 8, 8, 8, 
 +4, 4, 8, 8,  
 +4, 4, 4,  
 +2, 4 
 +}; 
 +void setup() 
 +
 +   ​pinMode(segA,​ OUTPUT); 
 +   ​pinMode(segB,​ OUTPUT); 
 +   ​pinMode(segC,​ OUTPUT); 
 +   ​pinMode(segD,​ OUTPUT); 
 +   ​pinMode(segE,​ OUTPUT); 
 +   ​pinMode(segF,​ OUTPUT); 
 +   ​pinMode(segG,​ OUTPUT); 
 +   ​pinMode(Dig1,​ OUTPUT); 
 +   ​pinMode(Dig2,​ OUTPUT); 
 +   ​pinMode(Dig3,​ OUTPUT); 
 +   ​pinMode(Dig4,​ OUTPUT); 
 +   ​Serial.begin(9600);​ 
 +   ​pinMode(nr,​ INPUT); 
 +
 +void loop() 
 +
 + ​buzzer.loop();​ 
 + int number; 
 + int x = analogRead(nr);​ 
 + ​Serial.print(x);​ 
 +  
 + duiz = false; 
 + hon = false; 
 + ​showNumber(x);​ 
 + if (x > 700) { 
 +    if (buzzer.getState() == BUZZER_IDLE) { 
 +      int length = sizeof(noteDurations) / sizeof(int);​ 
 +      buzzer.playMelody(melody,​ noteDurations,​ length); // playing 
 +    } 
 +  } 
 + 
 +  if (x <= 700) { 
 +    if (buzzer.getState() != BUZZER_IDLE) { 
 +      buzzer.stop() ; // stop 
 +    } 
 +  } 
 +
 + 
 +void showNumber(int x) { 
 +  for(int k = 0; k<50; k++){ // for loop to slow it down. 
 + 
 +   int figur = x; 
 +   ​for(int digit = 1 ; digit < 5 ; digit++) { //for loop to place the number in the right digit 
 +     ​switch(digit) { 
 +       case 1: 
 +       ​if(figur > 999){ 
 +         ​digitalWrite(Dig1,​ DIGIT_ON);​ 
 +         ​lightNumber(figur / 1000); // for example 2511 / 1000 = 2 
 +         figur %= 1000; // new value of figur = 511 figur = figur %1000 
 +         
 +         ​delayMicroseconds(DISPLAY_BRIGHTNESS);​ 
 +         if (figur < 100){ 
 +          duiz = true; 
 +         if (figur <10){ 
 +          hon = true; 
 +         } 
 +         
 +         }else duiz = false; 
 +       } 
 +       
 +       ​break;​ 
 +       case 2: 
 +       ​if(duiz == true){ 
 +          digitalWrite(Dig2,​ LOW); 
 +          lightNumber(0);​ 
 +          delayMicroseconds(DISPLAY_BRIGHTNESS);​ 
 +         
 +       ​}if(hon == true){ 
 +          break; 
 +       } 
 +       
 +       ​if(figur > 99 && figur < 1000){ 
 +         ​digitalWrite(Dig2,​ LOW); 
 +         ​lightNumber(figur / 100); 
 +         figur %= 100; 
 +         ​delayMicroseconds(DISPLAY_BRIGHTNESS);​ 
 +         if (figur < 10){ 
 +          hon = true; 
 +         
 +         }else hon = false; 
 +       } 
 +       ​break;​ 
 +       case 3: 
 +       ​if(hon == true){ 
 +         ​digitalWrite(Dig3,​ LOW); 
 +         ​lightNumber(0);​ 
 +         ​delayMicroseconds(DISPLAY_BRIGHTNESS);​ 
 +         ​break;​ 
 +       } 
 +       
 +       ​if(figur > 9 && figur < 100){ 
 +         ​digitalWrite(Dig3,​ LOW); 
 +         ​lightNumber(figur / 10); 
 +         figur %= 10; 
 +         ​delayMicroseconds(DISPLAY_BRIGHTNESS);​ 
 +       } 
 +       
 +       ​break;​ 
 +       case 4: 
 +       ​if(figur < 10){ 
 +         ​digitalWrite(Dig4,​ LOW); 
 +         ​lightNumber(figur);​ 
 +         ​delayMicroseconds(DISPLAY_BRIGHTNESS);​ 
 +         ​break;​ 
 +       } 
 +     } 
 +     //​Turn off all segments 
 +     ​lightNumber(10);​ 
 +     //​Turn off all digits 
 +     ​digitalWrite(Dig1,​ DIGIT_OFF);​ 
 +     ​digitalWrite(Dig2,​ DIGIT_OFF);​ 
 +     ​digitalWrite(Dig3,​ DIGIT_OFF);​ 
 +     ​digitalWrite(Dig4,​ DIGIT_OFF);​ 
 +   
 +    } 
 +  } 
 +
 + 
 + 
 +void lightNumber(int numberToDisplay) { 
 +  #define SEGMENT_ON LOW 
 +  #define SEGMENT_OFF HIGH 
 +  switch (numberToDisplay){ 
 +   case 0: 
 +   ​digitalWrite(segA,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segB,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segC,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segD,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segE,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segF,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segG,​ SEGMENT_OFF);​ 
 +   ​break;​ 
 +   case 1: 
 +   ​digitalWrite(segA,​ SEGMENT_OFF);​ 
 +   ​digitalWrite(segB,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segC,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segD,​ SEGMENT_OFF);​ 
 +   ​digitalWrite(segE,​ SEGMENT_OFF);​ 
 +   ​digitalWrite(segF,​ SEGMENT_OFF);​ 
 +   ​digitalWrite(segG,​ SEGMENT_OFF);​ 
 +   ​break;​ 
 +   case 2: 
 +   ​digitalWrite(segA,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segB,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segC,​ SEGMENT_OFF);​ 
 +   ​digitalWrite(segD,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segE,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segF,​ SEGMENT_OFF);​ 
 +   ​digitalWrite(segG,​ SEGMENT_ON);​ 
 +   ​break;​ 
 +   case 3: 
 +   ​digitalWrite(segA,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segB,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segC,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segD,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segE,​ SEGMENT_OFF);​ 
 +   ​digitalWrite(segF,​ SEGMENT_OFF);​ 
 +   ​digitalWrite(segG,​ SEGMENT_ON);​ 
 +   ​break;​ 
 +   case 4: 
 +   ​digitalWrite(segA,​ SEGMENT_OFF);​ 
 +   ​digitalWrite(segB,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segC,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segD,​ SEGMENT_OFF);​ 
 +   ​digitalWrite(segE,​ SEGMENT_OFF);​ 
 +   ​digitalWrite(segF,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segG,​ SEGMENT_ON);​ 
 +   ​break;​ 
 +   case 5: 
 +   ​digitalWrite(segA,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segB,​ SEGMENT_OFF);​ 
 +   ​digitalWrite(segC,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segD,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segE,​ SEGMENT_OFF);​ 
 +   ​digitalWrite(segF,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segG,​ SEGMENT_ON);​ 
 +   ​break;​ 
 +   case 6: 
 +   ​digitalWrite(segA,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segB,​ SEGMENT_OFF);​ 
 +   ​digitalWrite(segC,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segD,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segE,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segF,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segG,​ SEGMENT_ON);​ 
 +   ​break;​ 
 +   case 7: 
 +   ​digitalWrite(segA,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segB,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segC,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segD,​ SEGMENT_OFF);​ 
 +   ​digitalWrite(segE,​ SEGMENT_OFF);​ 
 +   ​digitalWrite(segF,​ SEGMENT_OFF);​ 
 +   ​digitalWrite(segG,​ SEGMENT_OFF);​ 
 +   ​break;​ 
 +   case 8: 
 +   ​digitalWrite(segA,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segB,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segC,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segD,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segE,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segF,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segG,​ SEGMENT_ON);​ 
 +   ​break;​ 
 +   case 9: 
 +   ​digitalWrite(segA,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segB,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segC,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segD,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segE,​ SEGMENT_OFF);​ 
 +   ​digitalWrite(segF,​ SEGMENT_ON);​ 
 +   ​digitalWrite(segG,​ SEGMENT_ON);​ 
 +   ​break;​ 
 +   case 10: 
 +   ​digitalWrite(segA,​ SEGMENT_OFF);​ 
 +   ​digitalWrite(segB,​ SEGMENT_OFF);​ 
 +   ​digitalWrite(segC,​ SEGMENT_OFF);​ 
 +   ​digitalWrite(segD,​ SEGMENT_OFF);​ 
 +   ​digitalWrite(segE,​ SEGMENT_OFF);​ 
 +   ​digitalWrite(segF,​ SEGMENT_OFF);​ 
 +   ​digitalWrite(segG,​ SEGMENT_OFF);​ 
 +   ​break;​ 
 +  } 
 +
 + 
 +</​code>​ 
 + 
 +{{:​pm:​prj2022:​arosca:​aplicatie-cod-dinu.png?300|}}
 ===== Rezultate Obţinute ===== ===== Rezultate Obţinute =====
 Foto proiect: Foto proiect:
Line 52: Line 431:
 Am avut cateva probleme cu placuta, dar s-au rezolvat in final. Per total sunt multumit de ce a iesit, dat fiind ca deviceul are si o utilitate in viata de zi cu zi. Am avut cateva probleme cu placuta, dar s-au rezolvat in final. Per total sunt multumit de ce a iesit, dat fiind ca deviceul are si o utilitate in viata de zi cu zi.
 ===== Download ===== ===== Download =====
- +{{:pm:prj2022:arosca:dinu_dumitru-razvan.zip|}}
-<note warning>​ +
-O arhivă (sau mai multe dacă este cazul) cu fişierele obţinute în urma realizării proiectului:​ surse, scheme, etc. Un fişier README, un ChangeLog, un script de compilare şi copiere automată pe uC crează întotdeauna o impresie bună ;-). +
- +
-Fişierele se încarcă pe wiki folosind facilitatea **Add Images or other files**. Namespace-ul în care se încarcă fişierele este de tipul **:pm:prj20??:c?** sau **:pm:​prj20??:​c?:​nume_student** (dacă este cazul). **Exemplu:​** Dumitru Alin, 331CC -> **:​pm:​prj2009:​cc:​dumitru_alin**. +
-</​note>​+
  
 ===== Jurnal ===== ===== Jurnal =====
Line 67: Line 441:
  
 ===== Bibliografie/​Resurse ===== ===== Bibliografie/​Resurse =====
 +Resurse Software:
 +
 +https://​arduinogetstarted.com/​faq/​how-to-use-buzzer-without-blocking-other-code
 +https://​arduinogetstarted.com/​tutorials/​arduino-buzzer-library
 +https://​github.com/​robsoncouto/​arduino-songs/​blob/​master/​merrychristmas/​merrychristmas.ino
 +
 +Resurse Hardware:
  
 +https://​lastminuteengineers.com/​mq2-gas-senser-arduino-tutorial/​
 +https://​howtomechatronics.com/​tutorials/​arduino/​arduino-and-hc-05-bluetooth-module-tutorial/​
 +https://​osoyoo.com/​2017/​08/​08/​4-digit-7-segment-led-display/​
  
 <​html><​a class="​media mediafile mf_pdf"​ href="?​do=export_pdf">​Export to PDF</​a></​html>​ <​html><​a class="​media mediafile mf_pdf"​ href="?​do=export_pdf">​Export to PDF</​a></​html>​
  
pm/prj2022/arosca/senzorgaze.1653682206.txt.gz · Last modified: 2022/05/27 23:10 by dumitru_razvan.dinu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0