arduino/maxuino sinewave generator on digital output


    Jan 09 2022 | 11:43 am
    Hi,
    does anyone knows if it is possible to generate frequencies on digital outputs of the arduino (with a piezzo) in max/msp? I know it's possible with "tone ()" function in arduino IDE but I can not find a way to do it in maxuino. The idea is to generate multiple frequencies on several digital output of the arduino.
    thank you,
    best

    • Jan 09 2022 | 4:09 pm
      My advice is to drop maxuino and any connection kits or similar and make simple max patch and arduino sketch to do what you want. depending on number of piezos connected, you might need TimerFreeTone() library instead of tone()
      https://bitbucket.org/teckel12/arduino-timer-free-tone/downloads/ ----------- Since few years firmataplus exists, aiming to enable use of tone library, but you won't find any trace of that in outdated maxuino. There are also not really well documented maxfirmata externals https://github.com/NullMember/MaxFirmata
      and so on...
      Again, dropping firmata would save you a lot of time, and at the end maybe you'll get what you want.
    • Jan 09 2022 | 5:07 pm
      +1 to that, it's really not hard to roll your own. "Exploring Arduino" is a great book.
    • Jan 09 2022 | 5:13 pm
      Thank you for your answers! I'm looking at all of these. The idea is to create a composition with a lot of piezos and I can not see how to realise it directly with Arduino IDE. (I know "tone()" is pretty easy to use but seems a bit limited) For sure it s possible to do it in max, even without maxuino. But can't see how for the moment.
    • Jan 09 2022 | 5:19 pm
      If you're not set on Arduino, it might be worth looking at the Daisy platform, on which you can run Gen~ exports.
    • Jan 10 2022 | 10:30 am
      Hi guys, I drop firmata/maxuino to use instead the [serial] object in max and the "TimerFreeTone" library of arduino. Obviously it seems much more relevant... Thanks for the advices ! I'm scratching my head now with how to send multiples variables from max to arduino. I manage to send one only with [serial] in max and with the "Serial.read" function in arduino. I hope I'm clear enough with my explainations. Do you know how to send/receive multiples values FROM max TO arduino (I found a great tutorial about how to do the oposite but nothing about this way...)
      thank you,
    • Jan 10 2022 | 11:00 am
      the optimal way to send values from max to arduino would depend on your plan with piezos. I mean if all would receive freq to play at same time, having same duration and volume ? Or individual, which again could in maximum have all 3 values included, freq, duration , volume. here is one example using prepended IDs for 6 arduino pins, followed by 3 values.
      #include <TimerFreeTone.h> byte inByte; void setup() {Serial.begin(57600);} // increased baud rate if really fast data needed
      void loop() {if (Serial.available() > 0) {inByte = Serial.read(); if (inByte == 'A'){int freq1 = Serial.parseInt(); int dur1 = Serial.parseInt(); int vol1 = Serial.parseInt(); TimerFreeTone(3, freq1, dur1, vol1);} if (inByte == 'B'){int freq2 = Serial.parseInt(); int dur2 = Serial.parseInt(); int vol2 = Serial.parseInt(); TimerFreeTone(4, freq2, dur2, vol2);} if (inByte == 'C'){int freq3 = Serial.parseInt(); int dur3 = Serial.parseInt(); int vol3 = Serial.parseInt(); TimerFreeTone(5, freq3, dur3, vol3);} if (inByte == 'D'){int freq4 = Serial.parseInt(); int dur4 = Serial.parseInt(); int vol4 = Serial.parseInt(); TimerFreeTone(6, freq4, dur4, vol4);} if (inByte == 'E'){int freq5 = Serial.parseInt(); int dur5 = Serial.parseInt(); int vol5 = Serial.parseInt(); TimerFreeTone(7, freq5, dur5, vol5);} if (inByte == 'F'){int freq6 = Serial.parseInt(); int dur6 = Serial.parseInt(); int vol6 = Serial.parseInt(); TimerFreeTone(8, freq6, dur6, vol6);} }}
      // SYNTAX: // TimerFreeTone( pin, frequency, duration [, volume ] ) - Play a note on pin at frequency in Hz for duration in milliseconds. // Parameters: // * pin - Pin speaker is wired to (other wire to ground, be sure to add an inline 100 ohm resistor). // * frequency - Play the specified frequency (should work fairly well in the 100 to 15000 Hz range). // * duration - Set the duration to play in milliseconds. Range: 0 to 65535 (65.5 seconds). // * volume - Optionally set the tone volume level (from 1 to 10), defaults to full volume (10).
      maxpatch
      -------------- one could remove volume if you don't need that. if you would prefer to send one long list containing only frequencies which would be distributed to pins with fixed duration and volume, things would look a bit more simple. But then all would sound at same time....
    • Jan 10 2022 | 6:17 pm
      Hi, thanks a lot for this. It seemed clear enough for me until... I tried it. It does not work and I don't know why. The arduino led is reacting but nothing comes from the piezo. (The wire is ok, I have sound in other ways). I'm not sure to understand the role of [atoi] but I have to work on it. If I understand your patch example I must have a 220hz sound during 250 miliseconds at the maximum (10) volum on the pin 3? (Refer to the first message object).
      thanks again for your time!
    • Jan 11 2022 | 12:50 pm
      Sorry to have troubled you with that mistake. In Arduino code I used Serial.parseInt(); for all values but in Max in pack 0. 0 0 I used float for the frequency, which should be so. So please simply replace all int freq1 = Serial.parseInt(); int freq1 = Serial.parseFloat(); etc. time and vol should keep parseInt -------- I guess you know that all tone() based libs are mono, means no matter how different outputs you use, at the end only one sound can be generated at a time.
    • Jan 11 2022 | 3:34 pm
      Hi, of course, it seemed to be the solution but still nothing is hapening... One more problem is that, if max is runing, I can not open the serial port of the arduino to print the values : it says "port busy"... This is not helping us to see what is hapening
    • Jan 11 2022 | 3:37 pm
      oh, and I changed "int freq1 = Serial.parseFloat();" with "float freq1 = Serial.parseFloat();" but still nothing
    • Jan 11 2022 | 4:43 pm
      send close message to serial object in max to close the port and allow arduio to upload code
    • Jan 11 2022 | 5:35 pm
      Ok i found the point : it's (inByte = 'A') instead of "==" Wow thank you very much
    • Jan 12 2022 | 12:55 pm
      yes, that was my typo in last message, sorry.
      To reply to your idea of using both max and arduino serial monitor at same time - that is not possible. Only one application can use selected serial port at a time.
      If you really need to monitor serial data, you can send it back to Max and parse it here, but in so simple code it is really not needed. -------- I must say that I am dissapointed with timerfreetone() because I expected it to be multytimbral capable, playing more simultaneous voices. But it is not the case, because it uses delaymicroseconds() to generate pulses, which puts generated tones in a queue, waiting for first to end, before playing next. At the moment, for "usual" arduinos one can produce as many voices as there are available hardware timers, using differnt Tone libs, and that depends on the processor in use. ESP32 boards should be able to play 16 voices to 16 piezos using ledcWriteTone(pin, frequency); or using tone32 library
      https://www.thomascountz.com/2021/02/21/arduino-tone-for-esp32 https://github.com/lbernstone/Tone32 --------- But if you only need to place mono voice into several piezos, you can do with simple tone or timerfree version. would work the same, and also having volume option might be handy.
    • Jan 12 2022 | 6:33 pm
      Hi,
      Just to answer about this (even if it seems to be another topic): " ...using both max and arduino serial monitor at same time - that is not possible. Only one application can use selected serial port at a time. " This guy is doing it very easily in his tutorial : https://www.youtube.com/watch?v=68L-WHh3Ows
      Back to the topic in hand, actually the "==" is used here and is working fine : http://www.noisemantra.com/Physical%20Computing/arduino-MaxMSP%20communications%2011.pdf So I'm a bit confused of what we have to use. But anyway, I'm still having the same problem : I want to make several sounds at the same time so tone() or FreeTimerTone() are not helping. Therefore, it is not possible to have simultaneous voices with a classic arduino board. The ESP32 seems to be the one but only for 16 voices. So why not with several EPS32 for more but this is another story... thanks again, I'm still hoping to find a way to do what I want!
    • Jan 13 2022 | 11:50 am
      Older Arduino versions (< 1.6.5) display error and refuse to communicate with the board if another app is using it.
      New Arduino version throws no error, and pretends as if it were ok, but in case other app is using same port, data will be interrupted, and code upload will fail. Same way, if serial monitor is open, and one tries to activate port in Max max will receive no data. If Max was first using the port, activating serial monitor in arduino will take over, but data to max will suffer, getting slow and interrupted. --------- So much about looking you tube tutorials. then, = and == are 2 different things if a == b is comparison a = b sets a to b --------- If you want to use more than 16 piezos, or better say polyphony for the composition, it looks you need several boards similar to ESP32. Or some clever voice management. If you need more independent piezos, but 16 voices polyphony would be enough, one could use I/O expanders like 74HC4067 to route pwm output to several destinations.
    • Jan 14 2022 | 10:10 am
      Ok, I ll check all of these options. Don't know how all of this would work with several boards plugged in, but should be achievable. Let's try first it with one ESP32 so!
      (I have to say I'm a bit surprised that nothing about similar projects have been already done)
      thanks
    • Jan 14 2022 | 12:42 pm
      I am actually not surprised no such thing was developed or at least published, it is too complicated for many channels as it would envolve several boards or external hardware and probably buzzer sound was not really interesting enough for such complexity. Back to ESP32, I did not see a direct option to adjust also volume, but one could do so by writing duty cycle together with frequency. ledcWriteTone(pin, frequency); ledcWrite(pin, duty); // duty = volume
      set PWM_RESOLUTION to 8-bit 0-255, (or 7-bit 0-127 to match midi notes velocity) ----- Maybe that way one could translate midi note-velocity into voice - freq - vol using poly in Max