Popisovaný nápad pochází z KinkLabu a ukazuje, jak snadno a levně lze s pomocí moderních technologií jednočipů řešit i poměrně složitá technická zadání.

Popisované zařízení slouží jako externí box pro připojení prakticky libovolné vibrační jednotky s napájecím napětím v rozmezí od 6 do cca 18V, alespoň principiálně řiditelné pulsně šířkovou modulací. S firmwarem, ocitovaným níže hračka umožňuje připojení k PC via USB a programové řízení nadřízeným počítačem (včetně nahrávání až pěti vlastních průběhů do EEPROM Arduina), program řízení rychlosti vibrace, řízení náběhových obálek a program rozmítání rychlosti mezi nastavenými hodnotami plus pět již zmíněných vlastních průběhů. Text není podrobným návodem ke stavbě, pojednán je spíše inspirativně :-)
Ke stavbě je zapotřebí - kromě vývojového kitu Arduino - už jen pár šuplíkových součástek. Konkrétně dva lineární potenciometry 10 kiloohm, přepínač 1x9, osm odporů po jednom kile, jeden zhruba desetiohmový odpor, výkonový N-MOSFET podle výkonu poháněného vibrátoru a Schottkyho diodu na ochranu tranzistoru před špičkami z motorku hračky. Celé schéma pak vypadá takto:

Ano, přepínač je opravdu vyřešen digitalizací napětí z odporového děliče. Zbývá firmware:
#include <EEPROM.h> #include <Messenger.h> /* VIBROCONTROLLER v0.1 by elims -Tato e-mailová adresa je chráněna před spamboty. Pro její zobrazení musíte mít povolen Javascript. Mode 0: PC-Mode Mode 1: const Mode 2: ramp Mode 3: fade Mode 4 - 8: Read wavetable from EEPROM */ // ### globals #################################################### Messenger message = Messenger(); //Instantiate the remote access int pwmpin = 6; // PWM for vibrator int indloadpin = 5; // Inductive load int modepin = 0; // Resistor kaskade (7x 1k) for mode selection int powerpin = 1; // 10k variable resistor for power int freqpin = 2; // 10k variable resistor for time int value = 0; // temporal value int address = 0; // global iterator int modevalue = 0; // float strength = 0; // variable to keep the actual PWM value (0-255) boolean rampup = true; // goes ramp up or down in byte mode = 0; // Stores the current Mode // ### functions ################################################### void fade(){ strength = float(analogRead(powerpin))/1024.0; if(value >= 255){ rampup = false; } if(value <= 0){ rampup = true; } if(rampup==true){ value += 5; } else { value -= 5; } analogWrite(pwmpin, int(float(value)*strength)); delay(analogRead(freqpin)/2+5); } void ramp(){ strength = float(analogRead(powerpin))/1024.0; if(value >= 255){ value = 0; } else { value += 5; } analogWrite(pwmpin, int(float(value)*strength)); delay(analogRead(freqpin)/2+5); } /* inverse ramp void iramp(){ strength = float(analogRead(powerpin))/1024.0; if(value <= 0){ value = 255; } else { value -= 5; } analogWrite(pwmpin, int(float(value)*strength)); delay(analogRead(freqpin)/2+5); } */ void tablelookup(int table){ strength = float(analogRead(powerpin))/1024.0; value = EEPROM.read(address + table*100); if(address >= 99){ address = 0; } else { address += 1; } analogWrite(pwmpin, int(float(value)*strength)); delay(analogRead(freqpin)/2+5); } // Create the callback function void messageReady() { if (message.available()) { // Checks to see if the message is complete and erases any previous messages if (mode > 0) { Serial.print('i'); Serial.print(' '); Serial.print(mode, DEC); Serial.println(); } else { switch (message.readChar()) { // Gets the first word as a character case 'r': // Read pins (analog or digital) readeeprom(); // Call the readpins function break; // Break from the switch case 'w': // Write pin writeeeprom(); // Call the writepin function break; case 's': setoutput(); break; case 'i': Serial.print('i'); Serial.print(' '); Serial.print(mode, DEC); Serial.println(); } } } } void readeeprom() { // Read pins (analog or digital) int table = 0; int add = 0; switch (message.readChar()) { // Gets the next word as a character case 'e': Serial.print('e'); Serial.print(' '); add = message.readInt(); Serial.print(add); Serial.print(' '); Serial.print(EEPROM.read(address), DEC); break; case 'p': Serial.print('p'); Serial.print(' '); table = message.readInt(); Serial.print(table); Serial.print(' '); for(int i = 0; i < 100; i++) { Serial.print(EEPROM.read(i + table*100), DEC); Serial.print(' '); } break; case 'a': // READ analog pins Serial.print('a'); // Echo what is being read Serial.print(' '); Serial.print(analogRead(powerpin)); Serial.print(' '); Serial.print(analogRead(freqpin)); Serial.print(' '); } Serial.println(); } void writeeeprom() { // Write pin int table = 0; int batch = 0; //multipurpose integer (adresse, batchadresse, formatvalue) switch (message.readChar()) { // Gets the next word as a character case 'e' : batch = message.readInt(); EEPROM.write(batch, message.readInt()); Serial.println('d'); break; case 'p': table = message.readInt(); batch = message.readInt(); for(byte i = 0; i < 10; i++) { EEPROM.write(i + batch * 10 + table*100, message.readInt()); } Serial.println('d'); break; case 'f': table = message.readInt(); batch = message.readInt(); for(byte i = 0; i < 100; i++) { EEPROM.write(i + table*100, batch); } Serial.println('d'); } } void setoutput() { switch (message.readChar()) { case 'a' : analogWrite(pwmpin, message.readInt()); //Sets the PWM of the pwmpin break; // Break from the switch case 'b' : analogWrite(indloadpin, message.readInt()); //Sets the PWM of the indloadpin } } // ### main ########################################### void setup() { Serial.begin(9600); // 115200 message.attach(messageReady); pinMode(pwmpin, OUTPUT); pinMode(indloadpin, OUTPUT); } void loop() { while (Serial.available()) message.process(Serial.read()); modevalue = analogRead(modepin)/4; if(modevalue >= 0 && modevalue < 16) { value = 0; //make sure ramp and fade start with 0 mode = 0; } if(modevalue >= 16 && modevalue < 48) { analogWrite(pwmpin, analogRead(powerpin)/4); mode = 1; } if(modevalue >= 48 && modevalue < 80) { mode = 2; ramp(); } if(modevalue >= 80 && modevalue < 112) { mode = 3; fade(); } if(modevalue >= 112 && modevalue < 144) { mode = 4; tablelookup(0); } if(modevalue >= 144 && modevalue < 176) { mode = 5; tablelookup(1); } if(modevalue >= 176 && modevalue < 208) { mode = 6; tablelookup(2); } if(modevalue >= 208 && modevalue < 240) { mode = 7; tablelookup(3); } if(modevalue >= 240 && modevalue < 257) { mode = 8; tablelookup(4); } }
