10 years, 3 months ago.

Irregular counting during for loops when trying to apply voltage on PCB via mBED pins.

Hallo there everyone, I seem to be in a bit of a pickle with one of my for loops.

The general problem and code

The issue happens in a simple function that I have written in order to send sequences of pulses to a PCB via one of the mBED pins. Here is the code (explanation of operation follows after both snippets of code):

Pulse sequence code

//==========FUNC 5=============
//Arbitrary pulse sequence generator.
//Notes: This function does not interfere with the test bench in any other way than calling PulseIT with the correct arguments, in the correct sequence and with suitable delays in between.

void Stim (float DLY, char lat, int M, int Nips, float Vips, float pwips, float dtips, float DT, int Ncon, float Vcon, float pwcon, float dtcon_pP, float dtcon_Pp)
{
    //DLY: Initial delay - delay before sequence start in s.
    //lat: Detects what is the `laterality' of the first pulse train (`i' = ipsilateral => All pulses in same direction, `c' = contralateral => Pulses in alternating directions).
    //M: Number of pulse `train-sets'. One train-set is a set of pulses with the same width, absolute amplitude, inter-pulse interval and laterality.
    //Nips: Number of ipsilateral pulses.
    //Vips: Amplitude of ips. pulses (can be negative) in V.
    //pwips: Width of ips. pulses in s.
    //dtips: Inter-pulse interval of ips. pulses in s.
    //DT: Interval between pulse trains of opposite polarities in s.
    //Ncon: Number of contralateral pulses.
    //Vcon: Amplitude of first pulse in con. train in V.
    //pwcon: Width of con. pulses in s.
    //dtcon_pP: Inter-pulse interval of con. pulses positive-to-negative (pre-Post) in s.
    //dtcon_Pp: Inter-pulse interval of con. pulses negative-to-positive (Post-pre) in s.

    modeRW = 1; //Set amplifier configuration to `write'.

    wait(DLY); //Delay start of paradigm by DLY (in seconds).
    int a = 0; //General purpose counter variable.
    int b = 0; //Counter for ips/con type pulse train alternations.
    
    for(b = 0; b < M; b++) //Sweep through ips/con stimulation trains.
    {
        if(lat == 'i'){ //If laterality is set to `ipsialteral'.
            for(a = 0; a < Nips-1; a++) //For each pulse in the `ips' train except the last one.
            {
                PulseIT(Vips, pwips); //Apply pulse as defined by input arguments.
                wait(dtips); //Leave inter-pulse interval of dtips (in seconds).
                printf("%f  ", Vips); //Show that a pulse has occured. Show amplitude of pulse.
            }
            
            //For the last pulse.
            if(Nips > 0){ //Checking whether we need any pulses in this train at all. (Prevents pulsing in case where Nips = 0)
                PulseIT(Vips, pwips); //Apply pulse as defined by input arguments.
                wait(DT); //Leave inter-pulse-train interval of DT (in seconds).
                printf("%f \n \r", Vips); //Show that a pulse has occured. Show amplitude of pulse.
            }
            
            lat = 'c'; //Flip laterality for next train-set of pulses.
        }
        else if(lat == 'c'){ //If laterality is set to `contralateral'.
            for(a = 0; a < Ncon-1; a++) //For each pulse in the `con' train except the last one.
            {
                PulseIT(Vcon, pwcon); //Apply pulse as defined by input arguments.
                if(Vcon > 0){ //If pulse is positive (`pre' flavour).
                    wait(dtcon_pP); //Leave inter-pulse interval of dtcon_pP (in seconds).
                }else{ //If pulse is negative (`Post' flavour).
                    wait(dtcon_Pp); //Leave inter-pulse interval of dtcon_Pp (in seconds).
                }
                printf("%f  ", Vcon); //Show that a pulse has occured. Show amplitude of pulse.
                Vcon = -Vcon; //Flip polarity of pulse.
            }
            
            //For the last pulse.
            if(Ncon > 0){ //Checking whether we need any pulses in this train at all. (Prevents pulsing in case where Nips = 0)
                PulseIT(Vcon, pwcon); //Apply pulse as defined by input arguments.
                wait(DT); //Leave inter-pulse-train interval of DT (in seconds).
                printf("%f \n \r", Vcon); //Show that a pulse has occured. Show amplitude of pulse.
            }
            
            lat = 'i'; //Flip laterality for next train-set of pulses.
        }
    }
}

where the single pulse function is shown here:

Single pulse function

//==========FUNC 4=============
//Write function
//Notes: This function applies pulses individually. Ideally suited for calling from MATLAB with a pre-defined stimulation pattern in mind.
//Caution: This function disconnects all bridging resistors and shuts the read-out port.

void PulseIT (float A, float pw) //A: Volts; pw: seconds.
{
    modeRW = 1; //Set operating mode to `write' configuration.
    biasM = 0; //Disconnect Vmem read function. If write pulse feeds through to the mBED it WILL blow it up!
    Control = midPoint + A/gainFront; // Apply write voltage to output port.
    wait(0.000005); // Allow output port voltage to settle.
    readBus=0; //Deactivate all bridging resistors.
    progM=1; // Connect Vmem (applied) voltage to cross-bar via by-pass path.
    wait(pw); // Pulse width, in seconds.
    progM=0; // Break by-pass path.
    Control = midPoint; // Bias voltage return to 0V.
}

What this code does is actually quite simple: It generates sequences of pulses of the same polarity (unipolar) followed by sequences of pulse pairs where each pulse has different polarity (bipolar). It can start either with a unipolar sequence or a bipolar sequence and pulse amplitudes, widths and various timings are all user-controllable. When the time comes to emit a pulse, function PulseIT is activated. That function simply controls the values of some digital and analogue pins.

Detailed description of the issue

The command I'm sending is this:

Call to Stim function.

Stim(/*DLY:*/0.001, /*lat:*/'i', /*M:*/3, /*Nips:*/9, /*Vips:*/0.5, /*pwips:*/0.001, /*dtips:*/0.001, /*DT:*/0.01, /*Ncon:*/12, /*Vcon:*/0.6, /*pwcon:*/0.002, /*dtcon_pP:*/0.002, /*dtcon_Pp:*/0.001); //Stim function check.

which to make a long story short is supposed to send a unipolar pulse sequence of 9 pulses, followed by a bipolar sequence of 12 pulses, followed by another unipolar sequence of 9 pulses. Instead what I get is shown in the image below:

/media/uploads/SOTONmbeds/count_glitch_anno.png

Note: The trace of interest is the yellow one. The purple one has no relation to the current situation whatsoever. It measures something irrelevant elsewhere on my PCB.

For some reason the unipolar sequence is interrupted after the emission of exactly 7 pulses. This occurs both with ms-scale pulses and with us-scale. The interruption is always after 7 pulses. Then, after a long delay the last 2 pulses are emitted, with great delay. Another great delay later (rather than the programmed 10ms) the bipolar pulse sequence starts and fails after 6 pulses. The other 6 follow with a delay. Then we get another unipolar sequence broken in a 7 + 2 configuration yet again. In summary, my 9uni + 12bi + 9uni sequence becomes 7uni + 2uni + 6bi + 6bi + 7uni + 2uni.

Interestingly, if I try a 12bi + 9uni + 12bi sequence it gets broken down into: 7bi + 5bi + 7uni + 2uni + 6bi + 6bi.

I have to say this weird behaviour has got me completely stumped... Any ideas anyone?

Thanks.

2 Answers

10 years, 3 months ago.

Hello,

Did you try the same code without printf(..)'s ? It would be interesting...

Regards,

thenoble66

Accepted Answer
Nano Group
poster
10 years, 3 months ago.

By my beard! You're right! Question now is why would it affect some loops more than others? Is it a matter of `buffer housekeeping'?

Thank you very much for the help! It's saved me a lot of head-banging!

Indeed, very likely that can be the cause.

You're welcome ;-)

posted by Gyozo Nemes 24 Jan 2014