Jump to content

Recommended Posts

Posted

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! 

 

Posted

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.

Posted

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(" ");
 
}
}

 
Posted

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.

Posted
/////////////////////////////////////////////////////////////////////////////
// Include files
/////////////////////////////////////////////////////////////////////////////
 
#include <mios32.h>
#include "app.h"
#include <stdbool.h>
 
const char* bool_to_string(bool value) {
return value ? "1" : "0";
}
Posted
// $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)
{
}
Posted

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!

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...