Scaling a value

This should be easy, but I'm struggling with getting it to work correctly.

I have a "sample", from an analog input, that I want to apply a 0 to 100% "gain", like a volume control.

Here is the part that isn't working, as soon as settings.ADC_Gain is less than 100, I get no sample value at all. I think it is because (settings.ADC_Gain/100) computes as zero in integer math, but I don't know how to make it a float result to apply to "sample"....

void loop() {
    unsigned long loop_start_time = micros(); // Used to track rate
    float sample, value;

    // Read ADC and apply "centering"
    sample = (float)analogRead(Analog_In) + settings.ADC_Centre;

    // Apply gain
    sample = sample * (settings.ADC_Gain/100);

.....etc.

Is this the correct syntax ?

    // Apply gain
    sample = sample * (float)(settings.ADC_Gain/100);

Is this the correct syntax ?

The syntax looks OK but you are doing integer arithmetic when dividing by 100

Try

sample = sample * (float)(settings.ADC_Gain/100.0);

to force the calculation to be done as a float

UKHeliBob:
The syntax looks OK but you are doing integer arithmetic when dividing by 100

Try

sample = sample * (float)(settings.ADC_Gain/100.0);

to force the calculation to be done as a float

Ahhh, the penny drops ! Thanks .....

It would be way more efficient to do the math in integers rather than converting from integers to floats and back.

sample = ((sample * settings.ADC_Gain)+50) / 100;

Warning: 'sample' can go up to 1023 and ADC_Gain can go up to 100 so the result of the multiply can go up to 102,300 which is too large for an int. You have to do the multiply in 'long' or 'unsigned long':

sample = ((sample * (long)settings.ADC_Gain)+50) / 100;

johnwasser:
It would be way more efficient to do the math in integers rather than converting from integers to floats and back.

sample = ((sample * settings.ADC_Gain)+50) / 100;

Warning: 'sample' can go up to 1023 and ADC_Gain can go up to 100 so the result of the multiply can go up to 102,300 which is too large for an int. You have to do the multiply in 'long' or 'unsigned long':

sample = ((sample * (long)settings.ADC_Gain)+50) / 100;

I have my scaling as ....

sample = sample * (float)(settings.ADC_Gain/100.0);

... so the gain factor is 0.0 to 1.0.

Not really interested in "efficiency" as such, at the end of void loop() the code sits in a bit of code that "wastes" clock cycles, so that loop() executes every 200 uS, the "sampling" is done at 5 kHz.

       // Consume excess clock cycles, to keep at 5000 hz
        for(unsigned long up = loop_start_time+LoopPeriod_uS; loop_start_time > 20 && loop_start_time < up; loop_start_time = micros());

Not sure I understand that line though.....

Although since I have added RemoteXY handler, I'm guessing it doesn't wait there very long, if at all. Think I might make a toggle and scope it to check on that. Having said that, the code is working far better than I expected, or desired. Video of it working here

The project is a "beat" detector that I have built into a DMX stage lighting controller to change scenes by bass sound. The original S-T-L circuit built into the controller was pretty dire, just a couple of op-amps and no attempt to capture bass notes or drum-beats, I could trigger it with my iPhone playing music, and there's no bass in that.