Jump to content

Preventing integer roll-over from analog-in readings?


sneakthief
 Share

Recommended Posts

I keep banging my head against Audiocommander's AC Sensorizer code.

 

This part of the code reads the 8 analog-in pins and then converts them to 7-bit MIDI cc (0-127) commands, but the problem is that sensors can cause this value to roll-over, regardless of the sensor minimum and maximum settings (sMax & sMin).

 

In other words, I keep getting MIDI cc's that roll-over and go 124, 125, 126, 127, 0, 1, 2, etc. - or 3, 2, 1, 0, 127, 126, 125, etc.

 

How can I prevent this?

// sense range
volatile unsigned int        sMin[SENSOR_NUM];        // 10-bit minimum sense (ignore below; => 7bit:   0)
volatile unsigned int        sMax[SENSOR_NUM];        // 10-bit maximum sense (ignore above; => 7bit: 127)
// expand signal
volatile unsigned char        sFactor[SENSOR_NUM];    // calibrated sensor factor: (sMax - sMin) / 127
                                                    //   if somehow possible use 1, 2, 4, 8 or 16
                                                    //   to use fastest bit-shifting algorithm
                                                    //   otherwise a complex multi-cycle division occurs
volatile unsigned char        sFrom[SENSOR_NUM];        // scale to target min value (e.g. 0)
volatile unsigned char        sTo[SENSOR_NUM];        // scale to target max value (e.g. 127)



/////////////////////////////////////////////////////////////////////////////
//    This function reads the 10-bit value from <pin> and sends a 7-bit inter-
//    polated value. The sensors must be calibrated (with autoSensing) to
//    obtain good sensor measurements.
/////////////////////////////////////////////////////////////////////////////

unsigned char ACSensorizer_Sensorize(unsigned char pin, unsigned int pin_value) __wparam
{
    // temp values
    unsigned char    value_7bit = 0;
    unsigned int    value_10bit = 0;
    
    // abort if OFF (disabled)
    if(! sensor[pin].enabled) { return SRETURN_ABORT; }
    
    // abort if pedal enabled & pedal is not down (=1)
    if((sensor[pin].pedalMode >= PEDAL_FILTER) && (sensorizer.pedalUp)) { return SRETURN_ABORT; }
    
    
    // abort if below sMin or above sMax
    if(pin_value < sMin[pin]) {
        if((sensor[pin].releaseDetect) && (lastAIN_value[pin] != 0)) {
            lastAIN_value[pin] = 0;
            return 0;                                    // send 0 to mute sound on release
        } else {
            return SRETURN_RELEASEDETECT;
        }
    }
    if(pin_value > sMax[pin]) { return SRETURN_ABORT; }
    
    
    // expand
    value_10bit = pin_value - sMin[pin];
    switch(sFactor[pin]) {
        case  1:    value_7bit = (unsigned char) value_10bit;        break;
        case  2:    value_7bit = (unsigned char)(value_10bit >> 1);    break;
        case  4:    value_7bit = (unsigned char)(value_10bit >> 2);    break;
        case  8:    value_7bit = (unsigned char)(value_10bit >> 3);    break;
        case 16:    value_7bit = (unsigned char)(value_10bit >> 4);    break;
        default:
            value_7bit = (unsigned char)ACMath_Divide(value_10bit, (unsigned int)sFactor[pin]);
            break;
    }
    
    // scale
    value_7bit = ACMath_Scale(value_7bit, sFrom[pin], sTo[pin]);
    
    // restrict to 7 bit MIDI-values
    if(value_7bit < sFrom[pin]) { return SRETURN_ABORT; }
    if(value_7bit > sTo[pin])    { return SRETURN_ABORT; }

    // don't send unchanged values
    if(value_7bit == lastAIN_value[pin]) { return SRETURN_ABORT; }
    // store last 10bit value
    lastAIN_value[pin] = value_7bit;
    lastAIN_10bitValue[pin] = value_10bit;
    // return success

    // invert
    if(sensor[pin].invert) {
        inverted_value = value_7bit - value_7bit - value_7bit;
        value_7bit = inverted_value + 127;    
        }
    
    
    return value_7bit;
}




 

 

 

Edited by sneakthief
Link to comment
Share on other sites

sFrom: 0

sTo: 127

sFactor: 1

My accelerometer (ADXL335) puts out 0-3V.

 

The closest I can get to midi CC's that don't always roll over is this:

 

sMin: 3

sMax: 98

 

But this setting still gives occasional integer rollovers from 0 to 127.

 

- If sMin > 4, the midi CC goes *always* rolls from 0 to 127, etc. as the accelerometer voltage approaches 0V.

 

- If sMin < 3, I can't reach anything under a midi CC value of 10

 

 

It makes no difference if it's inverted or not - I get the same problem.

 

Isn't there some way here to prevent an int from rolling over?

Link to comment
Share on other sites

Ok, I see the problem - the factor is too low (actually it's not a factor, but a divider which has to scale down the 10bit value into the 7bit range).

But apart from this configuration issue, it also makes sense to add a proper saturation.

 

So, here are the steps:

 

change:

unsigned char    value_7bit = 0;

 

to:

unsigned int     value_7bit = 0;

This ensures, that a rollover can be detected properly.

 

Before the ACMath_Scale call, write:

  if( value_7bit > 127 )
    value_7bit = 127;

 

 

This ensures that the conversion value is within the 0..127 range before it will be scaled.

 

Nevertheless, increase the "factor", otherwise the sensor will saturate to 127 quickly.

 

Best Regards, Thorsten.

Link to comment
Share on other sites

Perfect - I'm going to experiment with this! 

 

My first experiments with the "factor" were probably negative because my sensor became a lot more sluggish when I used higher factors, but I'll see what happens when I stick with a higher factor and adjust the other parameters around it.

 

Wie immer, vielen Dank - ich schaetze dieses ganzen MIDIbox Projekt sehr.

Edited by sneakthief
Link to comment
Share on other sites

1. Your suggestion worked perfectly: if( value_7bit > 127 ) value_7bit = 127;

 

2. Re. "factor is too low": anything other than 1 made things worse and prevented the full midi CC range.

 

If I use factor 2, then I can't access half of the cc range, regardless of what sMin or sMax are. I don't find that it gets saturated too quickly either.

 

3. Regardless of the factor, the resolution is bad over the whole range of the sensor. As I move the sensor over its 180 degrees of motion, I get midi CC jumps of 7 or 10 between values, even when moving it very slowly.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

×
×
  • Create New...