jrp Posted April 22 Report Posted April 22 Dear Forum, to drive electro magnetic actuators with some velocity sensitivity i am thinking about -instead of using 4 expensive Aout modules with the need of bipolar power: - mapping midi note on and velocity to 3 or 4 dio pins with a resistor ladder to get 8 or 16 voltage levels. I would tune the resistors to get a custom curve because solenoids need a minimum impulse to get moving (initial lowest level around 50%, then linear to 100% from there). Is this a reasonable idea? What Midibox App is a good starting point? Can this be done with MidiboxNG? From reading through the Manual i assume yes, but is it reasonable and fast enough for 24 3 or 4 bit outs? (Midifying a 2 octave Glockenspiel) Or should i start from scratch with a new mios32 app? I know a little C and i have worked through most of the tutorials.... but not much more. The documentation is superb, but still i feel a little lost... My solution is sure to have a lot of if statements, propably hard coding every velocity of every note value by hand... Or is it necessary to program a driver for a new "Midibox Aout_4Bit" module? (<- would be the thing i feel least confident about, no idea where to start...) As an alternative i tried using the pwm signal from dimmed LEDs in MidiboxNG, but that did not work very well bacause the pwm frequency is rather low (around 4 pulses in 10ms), to slow for very short trigger impulses. I am really excited to getting started with 32 bit Midibox - my last build was the MB Sid, quite some years ago :) Thanks for any comments! Quote
latigid on Posted April 23 Report Posted April 23 Maybe check out http://www.ucapps.de/mbhp_aout_lc.html I'm not sure what app would suit you best though. NG is probably the most flexible, depending on what you want to do. Quote
jrp Posted April 24 Author Report Posted April 24 Thanks! Since i need two octaves the resistor ladder cv-lc will not get me far. Using three Midibox_CV_NG would do the trick, but i consider this really overkill since i am pretty sure that i will not get more than 8, maybe 16 different amplitude levels with the solenoids and Glockenspiel. So 3 or 4 bit resolution should be ideal. I have since been looking once more into the dout example in the mios32 programming section. The code to adress 4 dout pins for every note to get 16 voltage levels should be very straight forward. I am sure to get something running over the weekend. I will see if there are any general design problems with this idea. Quote
jrp Posted April 25 Author Report Posted April 25 that was easier to code than i thought. I really enjoyed learning about this. I dont have my scope, my douts or any leds here, so i added some code to print the output pattern to the lcd. I noticed that if i put the clear_lcd command outside any of the function blocks, i get an error during compilation. No sure how this should be done. I found a workaround though... #include <stdbool.h> is needed at the top of main.c for the display of the boolean values on the lcd u8 start=0; // to clear the lcd... int velocity_4bit; ///////////////////////////////////////////////////////////////////////////// // This hook is called when a MIDI package has been received ///////////////////////////////////////////////////////////////////////////// void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package) { // toggle Status LED on each incoming MIDI package MIOS32_BOARD_LED_Set(0x0001, ~MIOS32_BOARD_LED_Get()); // no idea how and where else i can clear the lcd if( start == 0 ) { MIOS32_LCD_Clear(); start=1; } if( midi_package.type == NoteOn && midi_package.velocity > 0 ) { u8 dout_pin = (midi_package.note % 12)*4; velocity_4bit = midi_package.velocity >> 3; MIOS32_BOARD_J5_PinSet(dout_pin, !((velocity_4bit >> 3)) & 1); MIOS32_BOARD_J5_PinSet(dout_pin+1, !((velocity_4bit >> 2)) & 1); MIOS32_BOARD_J5_PinSet(dout_pin+2, !((velocity_4bit >> 1)) & 1); MIOS32_BOARD_J5_PinSet(dout_pin+3, !((velocity_4bit >> 0)) & 1); // Just for testing: Print to lcd: MIOS32_LCD_CursorSet(dout_pin, 0); // X, Y MIOS32_LCD_PrintString(bool_to_string((velocity_4bit >> 3) & 1)); MIOS32_LCD_CursorSet(dout_pin+1, 0); // X, Y MIOS32_LCD_PrintString(bool_to_string((velocity_4bit >> 2) & 1)); MIOS32_LCD_CursorSet(dout_pin+2, 0); // X, Y MIOS32_LCD_PrintString(bool_to_string((velocity_4bit >> 1) & 1)); MIOS32_LCD_CursorSet(dout_pin+3, 0); // X, Y MIOS32_LCD_PrintString(bool_to_string((velocity_4bit >> 0) & 1)); MIOS32_LCD_CursorSet(0, 1); MIOS32_LCD_PrintFormattedString("%02d:%02d", midi_package.velocity,velocity_4bit); } else if( (midi_package.type == NoteOff) || (midi_package.type == NoteOn && midi_package.velocity == 0) ) { u8 dout_pin = (midi_package.note % 12)*4; MIOS32_BOARD_J5_PinSet(dout_pin, 0); MIOS32_BOARD_J5_PinSet(dout_pin+1,0); MIOS32_BOARD_J5_PinSet(dout_pin+2,0); MIOS32_BOARD_J5_PinSet(dout_pin+3,0); //MIOS32_LCD_CursorSet(dout_pin, 0); // X, Y //MIOS32_LCD_PrintString(" "); } } Quote
jrp Posted April 25 Author Report Posted April 25 now i have to look into timers to get some way of resetting my pins after some ms. Solenoids don´t like to be "on" for long, and the glockenspiel needs only a short percussive hit. Quote
jrp Posted April 25 Author Report Posted April 25 ///////////////////////////////////////////////////////////////////////////// // Include files ///////////////////////////////////////////////////////////////////////////// #include <mios32.h> #include "app.h" #include <stdbool.h> const char* bool_to_string(bool value) { return value ? "1" : "0"; } Quote
jrp Posted April 26 Author Report Posted April 26 // $Id$ /* * MIOS32 Tutorial #020: LCD Output * see README.txt for details * * ========================================================================== * * Copyright (C) 2009 Thorsten Klose (tk@midibox.org) * Licensed for personal non-commercial use only. * All other rights reserved. * * ========================================================================== */ ///////////////////////////////////////////////////////////////////////////// // Include files ///////////////////////////////////////////////////////////////////////////// #include <mios32.h> #include "app.h" #include <stdbool.h> const char* bool_to_string(bool value) { return value ? "1" : "0"; //u8 velocity_dependent_timings[16]={20,18,17,16,14,13,10,10,10,10,10,10,10,10,10,10}; } u8 note_off_timers[24]; ///////////////////////////////////////////////////////////////////////////// // This hook is called after startup to initialize the application ///////////////////////////////////////////////////////////////////////////// void APP_Init(void) { // initialize all LEDs MIOS32_BOARD_LED_Init(0xffffffff); // initialize all pins of J5A, J5B and J5C as outputs in Push-Pull Mode int pin; for(pin=0; pin<12; ++pin) MIOS32_BOARD_J5_PinInit(pin, MIOS32_BOARD_PIN_MODE_OUTPUT_PP); int i; for(i=0; i<24; ++i) { note_off_timers[i]=0; } } ///////////////////////////////////////////////////////////////////////////// // This task is running endless in background ///////////////////////////////////////////////////////////////////////////// void APP_Background(void) { // clear LCD // MIOS32_LCD_Clear(); } ///////////////////////////////////////////////////////////////////////////// // This hook is called each mS from the main task which also handles DIN, ENC // and AIN events. You could add more jobs here, but they shouldn't consume // more than 300 uS to ensure the responsiveness of buttons, encoders, pots. // Alternatively you could create a dedicated task for application specific // jobs as explained in $MIOS32_PATH/apps/tutorials/006_rtos_tasks ///////////////////////////////////////////////////////////////////////////// void APP_Tick(void) { // PWM modulate the status LED (this is a sign of life) u32 timestamp = MIOS32_TIMESTAMP_Get(); MIOS32_BOARD_LED_Set(1, (timestamp % 20) <= ((timestamp / 100) % 10)); int i; for(i=0; i<24; ++i) { if( note_off_timers[i]>0) { --note_off_timers[i]; } else { int j = i*4; MIOS32_BOARD_J5_PinSet(j, 0); MIOS32_BOARD_J5_PinSet(j+1,0); MIOS32_BOARD_J5_PinSet(j+2,0); MIOS32_BOARD_J5_PinSet(j+3,0); MIOS32_LCD_CursorSet(j, 0); // X, Y MIOS32_LCD_PrintString(" "); } } } ///////////////////////////////////////////////////////////////////////////// // This hook is called each mS from the MIDI task which checks for incoming // MIDI events. You could add more MIDI related jobs here, but they shouldn't // consume more than 300 uS to ensure the responsiveness of incoming MIDI. ///////////////////////////////////////////////////////////////////////////// void APP_MIDI_Tick(void) { } u8 start=0; // to clear the lcd... int velocity_4bit; ///////////////////////////////////////////////////////////////////////////// // This hook is called when a MIDI package has been received ///////////////////////////////////////////////////////////////////////////// void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package) { // toggle Status LED on each incoming MIDI package MIOS32_BOARD_LED_Set(0x0001, ~MIOS32_BOARD_LED_Get()); // no idea how and where else i can clear the lcd if( start == 0 ) { MIOS32_LCD_Clear(); start=1; } if( midi_package.type == NoteOn && midi_package.velocity > 0 ) { u8 note_number = (midi_package.note % 12); u8 dout_pin = note_number * 4; velocity_4bit = midi_package.velocity >> 3; //note_off_timers[note_number] = velocity_dependant_timings[velocity_4bit]; MIOS32_BOARD_J5_PinSet(dout_pin, !((velocity_4bit >> 3)) & 1); MIOS32_BOARD_J5_PinSet(dout_pin+1, !((velocity_4bit >> 2)) & 1); MIOS32_BOARD_J5_PinSet(dout_pin+2, !((velocity_4bit >> 1)) & 1); MIOS32_BOARD_J5_PinSet(dout_pin+3, !((velocity_4bit >> 0)) & 1); // Just for testing: Print to lcd: MIOS32_LCD_CursorSet(dout_pin, 0); // X, Y MIOS32_LCD_PrintString(bool_to_string((velocity_4bit >> 3) & 1)); MIOS32_LCD_CursorSet(dout_pin+1, 0); // X, Y MIOS32_LCD_PrintString(bool_to_string((velocity_4bit >> 2) & 1)); MIOS32_LCD_CursorSet(dout_pin+2, 0); // X, Y MIOS32_LCD_PrintString(bool_to_string((velocity_4bit >> 1) & 1)); MIOS32_LCD_CursorSet(dout_pin+3, 0); // X, Y MIOS32_LCD_PrintString(bool_to_string((velocity_4bit >> 0) & 1)); note_off_timers[note_number] = 3000/(velocity_4bit*2); // just for testing, this has to be tested and maybe we want longer gate for low velocity MIOS32_LCD_CursorSet(0, 1); MIOS32_LCD_PrintFormattedString("%02d:%02d:%02d", midi_package.velocity,velocity_4bit,note_off_timers[note_number]); } else if( (midi_package.type == NoteOff) || (midi_package.type == NoteOn && midi_package.velocity == 0) ) { u8 dout_pin = (midi_package.note % 12)*4; MIOS32_BOARD_J5_PinSet(dout_pin, 0); MIOS32_BOARD_J5_PinSet(dout_pin+1,0); MIOS32_BOARD_J5_PinSet(dout_pin+2,0); MIOS32_BOARD_J5_PinSet(dout_pin+3,0); //MIOS32_LCD_CursorSet(dout_pin, 0); // X, Y //MIOS32_LCD_PrintString(" "); } } ///////////////////////////////////////////////////////////////////////////// // This hook is called before the shift register chain is scanned ///////////////////////////////////////////////////////////////////////////// void APP_SRIO_ServicePrepare(void) { } ///////////////////////////////////////////////////////////////////////////// // This hook is called after the shift register chain has been scanned ///////////////////////////////////////////////////////////////////////////// void APP_SRIO_ServiceFinish(void) { } ///////////////////////////////////////////////////////////////////////////// // This hook is called when a button has been toggled // pin_value is 1 when button released, and 0 when button pressed ///////////////////////////////////////////////////////////////////////////// void APP_DIN_NotifyToggle(u32 pin, u32 pin_value) { } ///////////////////////////////////////////////////////////////////////////// // This hook is called when an encoder has been moved // incrementer is positive when encoder has been turned clockwise, else // it is negative ///////////////////////////////////////////////////////////////////////////// void APP_ENC_NotifyChange(u32 encoder, s32 incrementer) { } ///////////////////////////////////////////////////////////////////////////// // This hook is called when a pot has been moved ///////////////////////////////////////////////////////////////////////////// void APP_AIN_NotifyChange(u32 pin, u32 pin_value) { } Quote
jrp Posted April 26 Author Report Posted April 26 If anyone is interested, this sort of works, turning off the pins/updating the lcd after a specified time. It works as in the J5 debounce tutorial 006_rtos_task. Thanks for all the great tutorials, they really provide a good starting point for people like me! Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.