Hi,
I use a Lilypad board to control 4 vibrators that work basically like speakers. I control them through the serial port to activate them and control the duration, frequency, amplitude and which vibrator to activate (possibly several at the same time).
So I plugged each of the vibrators to a PWM pin (3, 5, 9 and 11), added an amplifier transistor to provide a sufficient current etc.
I control the amplitude using analogOutput, and I generate the frequency I want using a for loop, with something similar to this http://web.media.mit.edu/~leah/LilyPad/07_sound.html. I just replaced digitalWrite by AnalogWrite, and added support for several pins at the same time. I also use delay instead of delayMicroseconds when the frequency is low since the delay is too high for delayMicroseconds (http://www.arduino.cc/en/Reference/DelayMicroseconds). The frequency range I use is around 10Hz to 400Hz.
void beep(byte pattern, long duration, unsigned int frequency, byte amplitude) const
{
int i;
long del = (long)(1000000 / ((long)frequency));
long looptime = (long)((duration * 1000) / (del * 2));
long udel = del % 1000;
long mdel = del / 1000;
for (i = 0 ; i < looptime ; i++)
{
for (int j = 0 ; j < 4 ; j++)
if (j < _nbtactors && (pattern & (0x01 << j)))
analogWrite(_pins[j], amplitude);
//delayMicroseconds is not accurate over 16383µs
if (del > 10000)
{
//delayMicroseconds(udel);
delay(mdel);
}
else
delayMicroseconds(del);
for (int j = 0 ; j < 4 ; j++)
if (j < _nbtactors && (pattern & (0x01 << j)))
analogWrite(_pins[j], 0);
if (del > 10000)
{
//delayMicroseconds(udel);
delay(mdel);
}
else
delayMicroseconds(del);
}
}
So If I understand correctly the analogOutput function generates a high frequency (compared to the ones I use) signal. So this function generates a low frequency square signal whose up states are full of "holes" of the high frequency signal.
Everything looks to work fine, however I have some problems when looking closely.
Sometimes (I am unsure about the circumstances) low frequencies vibrations are too long, and therefore the frequency is wrong. It is due to a too loo long delay. There are several factors that I suspect to influence on that:
- low accuracy of delay. However I am unsure that this could lead to a 16Hz vibration of 1s (delay of 31.25ms) lasting more than 2s.
- different settings of PWM pins. pin 5 uses timer0, pin 9 uses timer1 and pins 3 and 11 use timer2. Knowing that timer0 is used for millis and micros, is it possible that doing frequently analogOutput on pin 5 screws up the value of millis and micros? timer1 is a 16bit timer, does it change anything compared to others? timer0 uses fast PWM whereas others use Phase correct PWM. Can this have an influence on the accuracy of one or more pins?
I tried to disable interrupts around my function. However it looks like my program stops to handle incoming serial packets after a short duration. What happens if I receive packets on the serial port while the interrupts are disabled? If the packets are lost my data is randomly shifted and this explains why my program does not handle them anymore.
Is it possible to generate directly a low frequency signal on a pin with a given amplitude (voltage) for a certain duration? This could replace this ugly for loop. The tone function looks interesting, however it only uses one pin at a time, and it is not possible to change the amplitude. I looked at the documentation of timers and interrupts, but it looks complicated. I would appreciate tips from someone experienced with this.
Thank you