Problem with Controll of my Function from inside the loop

The code is pasted below.

The platform is an Arduino Due, and I have modified the variant.h file to produce 20kHz PWM

I am new to programming, and this is only my second piece of code.

It generates a sawtooth voltage ramp by PWM on pin6, and an accompanying square wave pulse on pin7.

I transmit this PWM signal via Fiber optic cable, and then smooth it out with a low pass filter and opamp buffer. This is for a remote controll for a special kind of Tesla Coil.

The code is a long series of loops controlled by "if" filters, where the ramp is built up by calculating the amplitude relative to the time.

When I wrote the code, the ramp was generated inside the main loop, and it runs well and does what it should do.

You can see a demonstration of it here:

To be able to turn this ramp off and on, I then declared the contents as a function (void ramp () )
So that I could poll a switch inside the main loop and direct focus on to the ramp function, when I want it to output a ramp.

The switch is connected to pin12, hardware debounced with 2mS of clean signal transition.

This is the way the posted code looks like, but there are a couple of problems, I will start with the biggest first:

When I turn the switch off, the code gets interupted inside the execution of the function, you can see it on the attached photo, where yellow is the square wave on pin7, Magenta is the lowpassfiltered sawtooth wave, and Cyan is the switch.

This is what I don't understand, the switch is in the main loop, but it interferes with the execution of the ramp function.

The way I see it, the processor should complete the ramp function before it goes back to the main loop ( void loop ) and read the switch.

How can I prevent the switch from interfering with the execution of the ramp function in the midle of it?

I am at my wits end, and any pointers will be greatly appreciated.

Cheers, Finn Hammer

//QCW DRSSTC Tesla coil Ramp generator.  29-10-2016. Finn Hammer



//Generates the ramp signal, that serves as control reference to the QCW Buck converter.

// UPSLOPE potentiometer controlls the pulse length
// AMPLITUDE potentiometer controlls the peak amplitude of the ramp
// SCALE potentiometer controlls ontime, while preserving upslope rate
// BPS potentiometer controlls the BPS
// WICK (trim)potentiometer controlls the voltage level of the wick period

// ............................ "Calling names and Pointing Fingers".............................

int analogInPin0 = A0;          // Analog input pin that the UPSLOPE potentiometer is attached to
int analogInPin1 = A1;          // Analog input pin that the SCALE potentiometer is attached to
int analogInPin2 = A2;          // Analog input pin that the AMPLITUDE potentiometer is attached to
int analogInPin3 = A3;          // Analog input pin that the BPS potentiometer is attached to
int analogInPin5 = A5;          // Analog input pin that the WICK potentiometer is attached to

int inPin = 12;                 // The number of the input pin of the "Run" switch

int switchValue;

float uppot;                    // Ramp Risetime mapped to microseconds
float uppot1;                   // Ramp Risetime after scalepot

float scalepot;                 // scalefactor mapped to 1-1000
float skewpot;                  // Not implemented yet
float BPSpot;                   // bps time (time between ramps)
float amplitudepot;             // Amplitude mapped to 8bit
float amplitudepot1;            // Amplitude after the scale pot

int pulsePin =  5;              // the number of the pulse pin
int pwmPin =  6;                // the number of the PWM pin

int wicklevel;                  // The short "Wick" period, before ramp starts to rise
float  amplup;                  // Amplitude of upslope relative to time
float  samplup;                 // sample of amplup, taken at last pass, before it vanishes in the code at top.
float ampldown;                 // Amplitude of downslope relative to time (deltatime)
int downtime ;                  // Time when ramp goes negative = 1/5th of uptime

volatile long T = 0;            // T is the time reference in the loops.
// Gets reset to zero every time the ramp starts.
volatile  long deltatime;       //time referred to top of slope.

volatile  long  nowtime ;    //Time operator for resetting T


void setup() {

  Serial.begin(38400);
  pinMode(pulsePin, OUTPUT);
  pinMode(pwmPin, OUTPUT);
  analogWriteResolution  (8);
  analogReadResolution (10);
  pinMode(inPin, INPUT);
  digitalWrite(12, HIGH);
}



void loop () {

  switchValue = digitalRead (inPin);

  if (switchValue == HIGH  )

    ramp ();
}


//delay (BPSpot);



void ramp()
{

  // ................Read the pots and Scale the values to suit what I want to do......................


  uppot = map(analogRead(analogInPin0), 0, 1023, 5000, 18000);       // Map the duration of the upslope to microseconds
  scalepot = map(analogRead(analogInPin1), 0, 1023, 150, 1000);        // Map scalepot
  BPSpot = map (analogRead(analogInPin3), 0, 1023, 20, 980);             // Map BPSpot to between 20-980uS
  amplitudepot = map (analogRead(analogInPin2), 0, 1023, 0, 255);  // map amplitude to 8bit,
  wicklevel = map (analogRead (analogInPin5), 0, 1023, 0, 60);


  uppot1 = (uppot / 1000) * scalepot;                     // Here the ramp is scaled to preserve ramp rate
  amplitudepot1 = (amplitudepot / 1000) * scalepot;       // Here the ramp is scaled to preserve ramp rate


  T = (micros() - nowtime);                       //here the loop-clock "T" is set (close) to zero

  if (T >= 5 && T <= 1500) analogWrite (pwmPin, wicklevel);   //Start of the "wick" part of the ramp, to start the oscillations

  if (T >= 800)digitalWrite (pulsePin, HIGH);     //Here the pulse to start the UD2.7C goes high

  if ( T > 1500 && T <= uppot1) {                 // this is the period where the ramp goes up

    amplup = wicklevel + ((amplitudepot1 - wicklevel ) * (T - 1500) / (uppot1 - 1500)); //Here I calculate the amplitude at _this_ time in _this_ loop

    samplup = amplup;    //here I store a sample of the amplitude for  use after T> uppot1

    analogWrite (pwmPin,  amplup);
  }               // and here the ramp is generated

  downtime = uppot1 / 5;                          //this sets the downslope length relative to the upslope

  deltatime = (T - uppot1);                       //this creates a new clock, starting at the top of the ramp

  ampldown = (samplup * (downtime - deltatime)) / downtime; //this line describes the downslope, relative to deltatime

  if (T > uppot1 && T < uppot1 + downtime)        // this line defines the down ramp time interval
  {

    analogWrite (pwmPin, ampldown  );                       // and here the downslope is generated
  }

  if ( T >= uppot1 + downtime )         //this defines interval between ramps
  {

    analogWrite (pwmPin, 0);            //rampsignal set to zero (buckconverter idling)
  }
  if ( T >= uppot1 + downtime + 600 )   // The UD2.7 pulse is delayed 600uS to allow ramp low pass filter to settle to 0
  {

    digitalWrite (pulsePin, LOW);       //signal to UD2.7C is terminated

    delay (BPSpot);                     //this sets the repetition rate between ramps

    nowtime = micros();                  //updating time operator, for loop clock reset

  }
}

I will wager that the original code did not have smileys in it.

To post code and/or error messages:

  1. Use CTRL-T in the Arduino IDE to autoformat your complete code.
  2. Paste the complete autoformatted code between code tags (the </> button)
    so that we can easily see and deal with your code.
  3. Paste the complete error message between code tags (the </> button)
    so that we can easily see and deal with your messages.
  4. If you already posted without code tags, you may add the code tags by
    editing your post. Do not change your existing posts in any other way.
    You may make additional posts as needed.

Before posting again, you should read the three locked topics at the top of the Programming Questions forum, and any links to which these posts point.

If your project involves wiring, please provide a schematic and/or a wiring diagram and/or a clear photograph of the wiring.

Good Luck!

vaj4088

Thank you for your kind guidance, I edited the post with the code tags, and it already looks much better.

I have taken up reading the suggested posts too.

To perhaps clarify the problem:

I read here:

that a function behaves like gosub in Basic.
To me, this means that when the function is called from within the loop, the program execution should get diverted to the function, and when the function has finished executing - ramp () takes 18 mS to finish - only then should program execution go back to the loop ().
(To find out that the switch has gone LOW, and therefore wait untill it goes HIGH again)
However, in my case, it appears that the small control loop is executed while the ramp function is running, so that when I open the switch in the main loop, while the ramp () function is executing, then the ramp () is stopped, and that won't do.

Cheeers, Finn Hammer

hammertone wrote (in part):

I edited the post with the code tags, and it already looks much better.

Yes, it looks much better and is easier to deal with, BUT YOU MISSED STEP #1, WHICH IS TO AUTOFORMAT YOUR CODE**!**

Yes, a C/C++ function behaves much as a gosub in Basic. Program execution is diverted to the function, and when the function returns, program execution picks up from where the function was called.

What makes you believe that your program is behaving otherwise?

Perhaps the name of the ramp() function is confusing you. The ramp() function generates one step of the ramp each time that it is called. There are no loops within the ramp() function. The loop() function is called repeatedly, and the loop() function calls ramp().

The oscilloscope photo shows the behavior that you created. If you want something else, you will have to do something else.

From the scope shot, you have pressed the button for nearly 160 ms. If ramp() takes 18ms, that means that ramp() is called 8 times.

If you only want it to be triggered once (rising edge or falling edge), habe a look at the statechange example that comes with the IDE.

vaj4088,

Thank you for your reply, your attention to my learning curve is much appreciated, and believe me, I would not be here if not I had already spent 3 full days trying to figure this out on my own.

vaj4088:
hammertone wrote (in part):

Yes, it looks much better and is easier to deal with, BUT YOU MISSED STEP #1, WHICH IS TO AUTOFORMAT YOUR CODE**!**

Copy that, and edited with autoformat.

vaj4088:
vaj4088 wrote (in part):

Program execution is diverted to the function, and when the function returns, program execution picks up from where the function was called.

What makes you believe that your program is behaving otherwise?

If you look at this picture:

where I have made a red circle around one instance of ramp(), you will see that ramp() is executed 3 times in full.
You will also see (in the blue circle), that during the forth execution of ramp(), at a time "T" around 6mS, where it is this part of the ramp() function that is being executed:

if ( T > 1500 && T <= uppot1) {                 // this is the period where the ramp goes up

    amplup = wicklevel + ((amplitudepot1 - wicklevel ) * (T - 1500) / (uppot1 - 1500)); //Here I calculate the amplitude at _this_ time in _this_ loop

    samplup = amplup;    //here I store a sample of the amplitude for  use after T> uppot1

    analogWrite (pwmPin,  amplup);               // and here the ramp is generated
}

That the execution of ramp() is terminated at the same time that the switch (cyan trace) goes low.

This is why I am puzzeled, because I was expecting that by declaring ramp() as a function, I would insure that it would get executed in full, before the switch was polled again.

I have not progressed far enough into programming, to yet master the use of interrupts, but it seems to me, that the way the switch is being read up in loop() actually behaves like an interrupt call that has higher priority in the code than ramp() has.

It is a workaround this behaviour that I am looking for. How can I assign highest priority to ramp() so that it always executes up and to the closing bracket, even when the switch goes low.

I hope this makes sense.

Cheers, Finn Hammer

Your ramp() function is basically non-blocking with exception of the last step; this is usually a good thing. It means that it actually is called far more than what you think (and what I thought); possibly a 1000 times or so.

You need to indicate to loop() that a single ramp is finished (and if it isn't, keep on calling ramp till it is finished).

/*
  ramp function
  returns:
    true if one ramp is completed else false
*/
bool ramp()
{
  ...
  ...
}

Assuming that this is the last part that needs to be executed and hence indicates when a single ramp is finished

  if ( T >= uppot1 + downtime + 600 )   // The UD2.7 pulse is delayed 600uS to allow ramp low pass filter to settle to 0
  {

    digitalWrite (pulsePin, LOW);       //signal to UD2.7C is terminated

    delay (BPSpot);                     //this sets the repetition rate between ramps

    nowtime = micros();                  //updating time operator, for loop clock reset

  }

If so, you can modify the code as below

/*
  ramp function
  returns:
    true if one ramp is completed else false
*/
bool ramp()
{
  ...
  ...

  if ( T >= uppot1 + downtime + 600 )   // The UD2.7 pulse is delayed 600uS to allow ramp low pass filter to settle to 0
  {

    digitalWrite (pulsePin, LOW);       //signal to UD2.7C is terminated

    delay (BPSpot);                     //this sets the repetition rate between ramps

    nowtime = micros();                  //updating time operator, for loop clock reset


    // indicate that a full ramp has been generated
    return true;

  }
  // indicate that ramp is not completed yet
  return false;
}

And now you can modify loop() to test for the return value.

void loop()
{
  // remember progress of ramp()
  static bool fRampCompleted = true;

  // check if ramp() is completed; if not, call it again
  if(fRampCompleted == false)
  {
    fRampCompleted = ramp();
  }

  switchValue = digitalRead (inPin);
  if (switchValue == HIGH  )
  {
    // start ramp() function
    fRampCompleted = false;
  }
}

sterretje,

Thank you for your comprehensive answer.

I have worked with Serial.print, google and //comment out for 6 hours now, trying to get a feel for what does what.

The code does not run as expected yet, the switch looses control and the code doesn't stop again.

Is this the right conditions that I put at the end?

    digitalWrite (pulsePin, LOW);       //signal to UD2.7C is terminated

    delay (BPSpot);                     //this sets the repetition rate between ramps

    nowtime = micros();                  //updating time operator, for loop clock reset

    fRampCompleted = true;

  }
  
  fRampCompleted = false;

}

Even if fRampCompleted = true/false is the right thing, I don't understand why the

fRampCompleted = true comes before fRampCompleted = false, but i guess that only shows how ignorant I am about the flow of the program execution.

Here is a picture of the breadboard and behind that, the 200A Buck converter that I hope to control with the ramp code.

Cheers, Finn Hammer

You showed a modified a part of my code without showing how it fits in the rest of the your code. Please post a fully updated code in a new reply.

Is fRampCompleted now a global variable?

Anyway, my modification assumes that the ramp is completed after the BPSpot delay and hence only then returns true. The return false applies to all other situations; it could also have been implemented in each of the other timing 'ifs'.

I probably don't have too much time till after the weekend but will try to follow the thread in the meantime and maybe help further.

Sterretje ,

You ask: Is fRampCompleted now a global variable? and I guess it is, as declared in the first line after the blurb.

Here is the code as of now, it starts up idle, after the first switch of the button, it runs forever, I'm afraid.

In the code below: The things I don't understand in loop() => I have asked the questions about as comments to the code. Hope it works well that way.

Thank you for your effort, and enjoy your weekend!

//QCW DRSSTC Tesla coil Ramp generator.  29-10-2016. Finn Hammer



//Generates the ramp signal, that serves as control reference to the QCW Buck converter.

// UPSLOPE potentiometer controlls the pulse length
// AMPLITUDE potentiometer controlls the peak amplitude of the ramp
// SCALE potentiometer controlls ontime, while preserving upslope rate
// BPS potentiometer controlls the BPS
// WICK (trim)potentiometer controlls the voltage level of the wick period

// ............................ "Calling names and Pointing Fingers".............................


bool fRampCompleted;            //Variable to check function progress (I guess ;-) )


int analogInPin0 = A0;          // Analog input pin that the UPSLOPE potentiometer is attached to
int analogInPin1 = A1;          // Analog input pin that the SCALE potentiometer is attached to
int analogInPin2 = A2;          // Analog input pin that the AMPLITUDE potentiometer is attached to
int analogInPin3 = A3;          // Analog input pin that the BPS potentiometer is attached to
int analogInPin5 = A5;          // Analog input pin that the WICK potentiometer is attached to

int inPin = 12;                 // The number of the input pin of the "Run" switch

int switchValue;

float uppot;                    // Ramp Risetime mapped to microseconds
float uppot1;                   // Ramp Risetime after scalepot

float scalepot;                 // scalefactor mapped to 1-1000
float skewpot;                  // Not implemented yet
float BPSpot;                   // bps time (time between ramps)
float amplitudepot;             // Amplitude mapped to 8bit
float amplitudepot1;            // Amplitude after the scale pot

int pulsePin =  5;              // the number of the pulse pin
int pwmPin =  6;                // the number of the PWM pin

int wicklevel;                  // The short "Wick" period, before ramp starts to rise
float  amplup;                  // Amplitude of upslope relative to time
float  samplup;                 // sample of amplup, taken at last pass, before it vanishes in the code at top.
float ampldown;                 // Amplitude of downslope relative to time (deltatime)
int downtime ;                  // Time when ramp goes negative = 1/5th of uptime


volatile long T = 0;            // T is the time reference in the loops.
// Gets reset to zero every time the ramp starts.
volatile  long deltatime;       //time referred to top of slope.

volatile  long  nowtime ;    //Time operator for resetting T


void setup() {

  Serial.begin(38400);
  pinMode(pulsePin, OUTPUT);
  pinMode(pwmPin, OUTPUT);
  analogWriteResolution  (8);
  analogReadResolution (10);
  pinMode(inPin, INPUT);
  digitalWrite(12, HIGH);
}

//Serial.print ( " rampCompleted  "  )
//Serial.println (rampCompleted)


void loop()
{
  // remember progress of ramp()
  static bool fRampCompleted = true;      // what does _static_ mean in front of bool?

  // check if ramp() is completed; if not, call it again
  if (fRampCompleted == false)
  {
    fRampCompleted = ramp();
  }

  switchValue = digitalRead (inPin);
  if (switchValue == HIGH  )
  {
    // start ramp() function
    fRampCompleted = false;     //since ramp() is now = fRampCompleted, does this mean that you start 
                                //ramp() with the condition that fRampCompleted = false
  }
}




bool ramp()
{


  // ................Read the pots and Scale the values to suit what I want to do......................


  uppot = map(analogRead(analogInPin0), 0, 1023, 5000, 18000);       // Map the duration of the upslope to microseconds
  scalepot = map(analogRead(analogInPin1), 0, 1023, 150, 1000);        // Map scalepot
  BPSpot = map (analogRead(analogInPin3), 0, 1023, 20, 980);             // Map BPSpot to between 20-980uS
  amplitudepot = map (analogRead(analogInPin2), 0, 1023, 0, 255);  // map amplitude to 8bit,
  wicklevel = map (analogRead (analogInPin5), 0, 1023, 0, 60);


  uppot1 = (uppot / 1000) * scalepot;                     // Here the ramp is scaled to preserve ramp rate
  amplitudepot1 = (amplitudepot / 1000) * scalepot;       // Here the ramp is scaled to preserve ramp rate


  T = (micros() - nowtime);                       //here the loop-clock "T" is set (close) to zero

  if (T >= 5 && T <= 1500) analogWrite (pwmPin, wicklevel);   //Start of the "wick" part of the ramp, to start the oscillations

  if (T >= 800)digitalWrite (pulsePin, HIGH);     //Here the pulse to start the UD2.7C goes high

  if ( T > 1500 && T <= uppot1) {                 // this is the period where the ramp goes up

    amplup = wicklevel + ((amplitudepot1 - wicklevel ) * (T - 1500) / (uppot1 - 1500)); //Here I calculate the amplitude at _this_ time in _this_ loop

    samplup = amplup;    //here I store a sample of the amplitude for  use after T> uppot1

    analogWrite (pwmPin,  amplup);
  }               // and here the ramp is generated

  downtime = uppot1 / 5;                          //this sets the downslope length relative to the upslope

  deltatime = (T - uppot1);                       //this creates a new clock, starting at the top of the ramp

  ampldown = (samplup * (downtime - deltatime)) / downtime; //this line describes the downslope, relative to deltatime

  if (T > uppot1 && T < uppot1 + downtime)        // this line defines the down ramp time interval
  {

    analogWrite (pwmPin, ampldown  );                       // and here the downslope is generated
  }

  if ( T >= uppot1 + downtime )         //this defines interval between ramps
  {

    analogWrite (pwmPin, 0);            //rampsignal set to zero (buckconverter idling)
  }
  if ( T >= uppot1 + downtime + 600 )   // The UD2.7 pulse is delayed 600uS to allow ramp low pass filter to settle to 0
  {

    digitalWrite (pulsePin, LOW);       //signal to UD2.7C is terminated

    delay (BPSpot);                     //this sets the repetition rate between ramps

    nowtime = micros();                  //updating time operator, for loop clock reset

    fRampCompleted = true;

  }

  fRampCompleted = false;

}

Ok, you have a global fRampCompleted (the one in the beginning of the 'blurb') and a local one in loop(); those are not the same variables. The local one also hides the global one.

In ramp() you manipulate the global one and in loop() you test the local one.

If you remove the line starting with 'static bool', it will work as I intended.

And you should change 'bool ramp ()' to 'void ramp ()' because ramp () no longrr returns a bool.

I commented the line with static bool.... out, as you suggested

and that does not change things.

If I also change bool ramp() to void ramp() I get this error message

Arduino: 1.6.12 (Windows 7), Board: "Arduino Due (Programming Port)"

C:\Program Files (x86)\Arduino\arduino-builder -dump-prefs -logger=machine -hardware C:\Program Files (x86)\Arduino\hardware -hardware C:\Users\Finn\AppData\Local\Arduino15\packages -tools C:\Program Files (x86)\Arduino\tools-builder -tools C:\Program Files (x86)\Arduino\hardware\tools\avr -tools C:\Users\Finn\AppData\Local\Arduino15\packages -built-in-libraries C:\Program Files (x86)\Arduino\libraries -libraries C:\Users\Finn\Documents\Arduino\libraries -fqbn=arduino:sam:arduino_due_x_dbg -vid-pid=0X2A03_0X003D -ide-version=10612 -build-path C:\Users\Finn\AppData\Local\Temp\arduino_build_836718 -warnings=none -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.arm-none-eabi-gcc.path=C:\Users\Finn\AppData\Local\Arduino15\packages\arduino\tools\arm-none-eabi-gcc\4.8.3-2014q1 -prefs=runtime.tools.bossac.path=C:\Users\Finn\AppData\Local\Arduino15\packages\arduino\tools\bossac\1.6.1-arduino -verbose C:\Users\Finn\Desktop\rampgenerator\rampgeneratorNoSkew\rampgeneratorNoSkew.ino
C:\Program Files (x86)\Arduino\arduino-builder -compile -logger=machine -hardware C:\Program Files (x86)\Arduino\hardware -hardware C:\Users\Finn\AppData\Local\Arduino15\packages -tools C:\Program Files (x86)\Arduino\tools-builder -tools C:\Program Files (x86)\Arduino\hardware\tools\avr -tools C:\Users\Finn\AppData\Local\Arduino15\packages -built-in-libraries C:\Program Files (x86)\Arduino\libraries -libraries C:\Users\Finn\Documents\Arduino\libraries -fqbn=arduino:sam:arduino_due_x_dbg -vid-pid=0X2A03_0X003D -ide-version=10612 -build-path C:\Users\Finn\AppData\Local\Temp\arduino_build_836718 -warnings=none -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.arm-none-eabi-gcc.path=C:\Users\Finn\AppData\Local\Arduino15\packages\arduino\tools\arm-none-eabi-gcc\4.8.3-2014q1 -prefs=runtime.tools.bossac.path=C:\Users\Finn\AppData\Local\Arduino15\packages\arduino\tools\bossac\1.6.1-arduino -verbose C:\Users\Finn\Desktop\rampgenerator\rampgeneratorNoSkew\rampgeneratorNoSkew.ino
Using board 'arduino_due_x_dbg' from platform in folder: C:\Users\Finn\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.9
Using core 'arduino' from platform in folder: C:\Users\Finn\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.9
Detecting libraries used...
"C:\Users\Finn\AppData\Local\Arduino15\packages\arduino\tools\arm-none-eabi-gcc\4.8.3-2014q1/bin/arm-none-eabi-g++" -c -g -Os -w -std=gnu++11 -ffunction-sections -fdata-sections -nostdlib -fno-threadsafe-statics --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -Dprintf=iprintf  -w -x c++ -E -CC -mcpu=cortex-m3 -mthumb -DF_CPU=84000000L -DARDUINO=10612 -DARDUINO_SAM_DUE -DARDUINO_ARCH_SAM  -D__SAM3X8E__ -mthumb -DUSB_VID=0x2341 -DUSB_PID=0x003e -DUSBCON '-DUSB_MANUFACTURER="Arduino LLC"' '-DUSB_PRODUCT="Arduino Due"' "-IC:\Users\Finn\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.9\system/libsam" "-IC:\Users\Finn\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.9\system/CMSIS/CMSIS/Include/" "-IC:\Users\Finn\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.9\system/CMSIS/Device/ATMEL/" "-IC:\Users\Finn\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.9\cores\arduino" "-IC:\Users\Finn\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.9\variants\arduino_due_x" "C:\Users\Finn\AppData\Local\Temp\arduino_build_836718\sketch\rampgeneratorNoSkew.ino.cpp" -o "nul"
Generating function prototypes...
"C:\Users\Finn\AppData\Local\Arduino15\packages\arduino\tools\arm-none-eabi-gcc\4.8.3-2014q1/bin/arm-none-eabi-g++" -c -g -Os -w -std=gnu++11 -ffunction-sections -fdata-sections -nostdlib -fno-threadsafe-statics --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -Dprintf=iprintf  -w -x c++ -E -CC -mcpu=cortex-m3 -mthumb -DF_CPU=84000000L -DARDUINO=10612 -DARDUINO_SAM_DUE -DARDUINO_ARCH_SAM  -D__SAM3X8E__ -mthumb -DUSB_VID=0x2341 -DUSB_PID=0x003e -DUSBCON '-DUSB_MANUFACTURER="Arduino LLC"' '-DUSB_PRODUCT="Arduino Due"' "-IC:\Users\Finn\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.9\system/libsam" "-IC:\Users\Finn\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.9\system/CMSIS/CMSIS/Include/" "-IC:\Users\Finn\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.9\system/CMSIS/Device/ATMEL/" "-IC:\Users\Finn\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.9\cores\arduino" "-IC:\Users\Finn\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.9\variants\arduino_due_x" "C:\Users\Finn\AppData\Local\Temp\arduino_build_836718\sketch\rampgeneratorNoSkew.ino.cpp" -o "C:\Users\Finn\AppData\Local\Temp\arduino_build_836718\preproc\ctags_target_for_gcc_minus_e.cpp"
"C:\Program Files (x86)\Arduino\tools-builder\ctags\5.8-arduino10/ctags" -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives "C:\Users\Finn\AppData\Local\Temp\arduino_build_836718\preproc\ctags_target_for_gcc_minus_e.cpp"
Compiling sketch...
"C:\Users\Finn\AppData\Local\Arduino15\packages\arduino\tools\arm-none-eabi-gcc\4.8.3-2014q1/bin/arm-none-eabi-g++" -c -g -Os -w -std=gnu++11 -ffunction-sections -fdata-sections -nostdlib -fno-threadsafe-statics --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -Dprintf=iprintf -MMD -mcpu=cortex-m3 -mthumb -DF_CPU=84000000L -DARDUINO=10612 -DARDUINO_SAM_DUE -DARDUINO_ARCH_SAM  -D__SAM3X8E__ -mthumb -DUSB_VID=0x2341 -DUSB_PID=0x003e -DUSBCON '-DUSB_MANUFACTURER="Arduino LLC"' '-DUSB_PRODUCT="Arduino Due"' "-IC:\Users\Finn\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.9\system/libsam" "-IC:\Users\Finn\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.9\system/CMSIS/CMSIS/Include/" "-IC:\Users\Finn\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.9\system/CMSIS/Device/ATMEL/" "-IC:\Users\Finn\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.9\cores\arduino" "-IC:\Users\Finn\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.9\variants\arduino_due_x" "C:\Users\Finn\AppData\Local\Temp\arduino_build_836718\sketch\rampgeneratorNoSkew.ino.cpp" -o "C:\Users\Finn\AppData\Local\Temp\arduino_build_836718\sketch\rampgeneratorNoSkew.ino.cpp.o"
C:\Users\Finn\Desktop\rampgenerator\rampgeneratorNoSkew\rampgeneratorNoSkew.ino: In function 'void loop()':

rampgeneratorNoSkew:79: error: void value not ignored as it ought to be

     fRampCompleted = ramp();

                    ^

exit status 1
void value not ignored as it ought to be

The present code is here: (will produce too long a message for this board, so i put it in the next post.

Cheers, Finn Hammer

Here is the code that still runs forever, it even starts up from a board reset, without any input from the switch.

//QCW DRSSTC Tesla coil Ramp generator.  29-10-2016. Finn Hammer



//Generates the ramp signal, that serves as control reference to the QCW Buck converter.

// UPSLOPE potentiometer controlls the pulse length
// AMPLITUDE potentiometer controlls the peak amplitude of the ramp
// SCALE potentiometer controlls ontime, while preserving upslope rate
// BPS potentiometer controlls the BPS
// WICK (trim)potentiometer controlls the voltage level of the wick period

// ............................ "Calling names and Pointing Fingers".............................


bool fRampCompleted;            //Variable to check function progress (I guess ;-) )


int analogInPin0 = A0;          // Analog input pin that the UPSLOPE potentiometer is attached to
int analogInPin1 = A1;          // Analog input pin that the SCALE potentiometer is attached to
int analogInPin2 = A2;          // Analog input pin that the AMPLITUDE potentiometer is attached to
int analogInPin3 = A3;          // Analog input pin that the BPS potentiometer is attached to
int analogInPin5 = A5;          // Analog input pin that the WICK potentiometer is attached to

int inPin = 12;                 // The number of the input pin of the "Run" switch

int switchValue;

float uppot;                    // Ramp Risetime mapped to microseconds
float uppot1;                   // Ramp Risetime after scalepot

float scalepot;                 // scalefactor mapped to 1-1000
float skewpot;                  // Not implemented yet
float BPSpot;                   // bps time (time between ramps)
float amplitudepot;             // Amplitude mapped to 8bit
float amplitudepot1;            // Amplitude after the scale pot

int pulsePin =  5;              // the number of the pulse pin
int pwmPin =  6;                // the number of the PWM pin

int wicklevel;                  // The short "Wick" period, before ramp starts to rise
float  amplup;                  // Amplitude of upslope relative to time
float  samplup;                 // sample of amplup, taken at last pass, before it vanishes in the code at top.
float ampldown;                 // Amplitude of downslope relative to time (deltatime)
int downtime ;                  // Time when ramp goes negative = 1/5th of uptime


volatile long T = 0;            // T is the time reference in the loops.
// Gets reset to zero every time the ramp starts.
volatile  long deltatime;       //time referred to top of slope.

volatile  long  nowtime ;    //Time operator for resetting T


void setup() {

  Serial.begin(38400);
  pinMode(pulsePin, OUTPUT);
  pinMode(pwmPin, OUTPUT);
  analogWriteResolution  (8);
  analogReadResolution (10);
  pinMode(inPin, INPUT);
  digitalWrite(12, HIGH);
}

//Serial.print ( " rampCompleted  "  )
//Serial.println (rampCompleted)


void loop()
{
  // remember progress of ramp()
  // static bool fRampCompleted = true;      // what does _static_ mean in front of bool?

  // check if ramp() is completed; if not, call it again
  if (fRampCompleted == false)
  {
    fRampCompleted = ramp();
  }

  switchValue = digitalRead (inPin);
  if (switchValue == HIGH  )
  {
    // start ramp() function
    fRampCompleted = false;     //since ramp() is now = fRampCompleted, does this mean that you start
    //ramp() with the condition that fRampCompleted = false
  }
}




void ramp()
{


  // ................Read the pots and Scale the values to suit what I want to do......................


  uppot = map(analogRead(analogInPin0), 0, 1023, 5000, 18000);       // Map the duration of the upslope to microseconds
  scalepot = map(analogRead(analogInPin1), 0, 1023, 150, 1000);        // Map scalepot
  BPSpot = map (analogRead(analogInPin3), 0, 1023, 20, 980);             // Map BPSpot to between 20-980uS
  amplitudepot = map (analogRead(analogInPin2), 0, 1023, 0, 255);  // map amplitude to 8bit,
  wicklevel = map (analogRead (analogInPin5), 0, 1023, 0, 60);


  uppot1 = (uppot / 1000) * scalepot;                     // Here the ramp is scaled to preserve ramp rate
  amplitudepot1 = (amplitudepot / 1000) * scalepot;       // Here the ramp is scaled to preserve ramp rate


  T = (micros() - nowtime);                       //here the loop-clock "T" is set (close) to zero

  if (T >= 5 && T <= 1500) analogWrite (pwmPin, wicklevel);   //Start of the "wick" part of the ramp, to start the oscillations

  if (T >= 800)digitalWrite (pulsePin, HIGH);     //Here the pulse to start the UD2.7C goes high

  if ( T > 1500 && T <= uppot1) {                 // this is the period where the ramp goes up

    amplup = wicklevel + ((amplitudepot1 - wicklevel ) * (T - 1500) / (uppot1 - 1500)); //Here I calculate the amplitude at _this_ time in _this_ loop

    samplup = amplup;    //here I store a sample of the amplitude for  use after T> uppot1

    analogWrite (pwmPin,  amplup);
  }               // and here the ramp is generated

  downtime = uppot1 / 5;                          //this sets the downslope length relative to the upslope

  deltatime = (T - uppot1);                       //this creates a new clock, starting at the top of the ramp

  ampldown = (samplup * (downtime - deltatime)) / downtime; //this line describes the downslope, relative to deltatime

  if (T > uppot1 && T < uppot1 + downtime)        // this line defines the down ramp time interval
  {

    analogWrite (pwmPin, ampldown  );                       // and here the downslope is generated
  }

  if ( T >= uppot1 + downtime )         //this defines interval between ramps
  {

    analogWrite (pwmPin, 0);            //rampsignal set to zero (buckconverter idling)
  }
  if ( T >= uppot1 + downtime + 600 )   // The UD2.7 pulse is delayed 600uS to allow ramp low pass filter to settle to 0
  {

    digitalWrite (pulsePin, LOW);       //signal to UD2.7C is terminated

    delay (BPSpot);                     //this sets the repetition rate between ramps

    nowtime = micros();                  //updating time operator, for loop clock reset

    fRampCompleted = true;

  }

  fRampCompleted = false;

}

Sorry, my mistake. I missed that you still use the return value in loop().

To compensate ( :wink: ) the complete code as I thought it should be; I've removed the global fRampCompleted.

//QCW DRSSTC Tesla coil Ramp generator.  29-10-2016. Finn Hammer



//Generates the ramp signal, that serves as control reference to the QCW Buck converter.

// UPSLOPE potentiometer controlls the pulse length
// AMPLITUDE potentiometer controlls the peak amplitude of the ramp
// SCALE potentiometer controlls ontime, while preserving upslope rate
// BPS potentiometer controlls the BPS
// WICK (trim)potentiometer controlls the voltage level of the wick period

// ............................ "Calling names and Pointing Fingers".............................

int analogInPin0 = A0;          // Analog input pin that the UPSLOPE potentiometer is attached to
int analogInPin1 = A1;          // Analog input pin that the SCALE potentiometer is attached to
int analogInPin2 = A2;          // Analog input pin that the AMPLITUDE potentiometer is attached to
int analogInPin3 = A3;          // Analog input pin that the BPS potentiometer is attached to
int analogInPin5 = A5;          // Analog input pin that the WICK potentiometer is attached to

int inPin = 12;                 // The number of the input pin of the "Run" switch

int switchValue;

float uppot;                    // Ramp Risetime mapped to microseconds
float uppot1;                   // Ramp Risetime after scalepot

float scalepot;                 // scalefactor mapped to 1-1000
float skewpot;                  // Not implemented yet
float BPSpot;                   // bps time (time between ramps)
float amplitudepot;             // Amplitude mapped to 8bit
float amplitudepot1;            // Amplitude after the scale pot

int pulsePin =  5;              // the number of the pulse pin
int pwmPin =  6;                // the number of the PWM pin

int wicklevel;                  // The short "Wick" period, before ramp starts to rise
float  amplup;                  // Amplitude of upslope relative to time
float  samplup;                 // sample of amplup, taken at last pass, before it vanishes in the code at top.
float ampldown;                 // Amplitude of downslope relative to time (deltatime)
int downtime ;                  // Time when ramp goes negative = 1/5th of uptime


volatile long T = 0;            // T is the time reference in the loops.
// Gets reset to zero every time the ramp starts.
volatile  long deltatime;       //time referred to top of slope.

volatile  long  nowtime ;    //Time operator for resetting T


void setup()
{

  Serial.begin(38400);
  pinMode(pulsePin, OUTPUT);
  pinMode(pwmPin, OUTPUT);
  analogWriteResolution  (8);
  analogReadResolution (10);
  pinMode(inPin, INPUT);
  digitalWrite(12, HIGH);
}

//Serial.print ( " rampCompleted  "  )
//Serial.println (rampCompleted)


void loop()
{
  // remember progress of ramp()
  static bool fRampCompleted = true;      // what does _static_ mean in front of bool?

  // check if ramp() is completed; if not, call it again
  if (fRampCompleted == false)
  {
    fRampCompleted = ramp();
  }

  switchValue = digitalRead (inPin);
  if (switchValue == HIGH  )
  {
    // start ramp() function
    fRampCompleted = false;     //since ramp() is now = fRampCompleted, does this mean that you start
  }
}




bool ramp()
{


  // ................Read the pots and Scale the values to suit what I want to do......................


  uppot = map(analogRead(analogInPin0), 0, 1023, 5000, 18000);       // Map the duration of the upslope to microseconds
  scalepot = map(analogRead(analogInPin1), 0, 1023, 150, 1000);        // Map scalepot
  BPSpot = map (analogRead(analogInPin3), 0, 1023, 20, 980);             // Map BPSpot to between 20-980uS
  amplitudepot = map (analogRead(analogInPin2), 0, 1023, 0, 255);  // map amplitude to 8bit,
  wicklevel = map (analogRead (analogInPin5), 0, 1023, 0, 60);


  uppot1 = (uppot / 1000) * scalepot;                     // Here the ramp is scaled to preserve ramp rate
  amplitudepot1 = (amplitudepot / 1000) * scalepot;       // Here the ramp is scaled to preserve ramp rate


  T = (micros() - nowtime);                       //here the loop-clock "T" is set (close) to zero

  if (T >= 5 && T <= 1500) analogWrite (pwmPin, wicklevel);   //Start of the "wick" part of the ramp, to start the oscillations

  if (T >= 800)digitalWrite (pulsePin, HIGH);     //Here the pulse to start the UD2.7C goes high

  if ( T > 1500 && T <= uppot1)                   // this is the period where the ramp goes up
  {

    amplup = wicklevel + ((amplitudepot1 - wicklevel ) * (T - 1500) / (uppot1 - 1500)); //Here I calculate the amplitude at _this_ time in _this_ loop

    samplup = amplup;    //here I store a sample of the amplitude for  use after T> uppot1

    analogWrite (pwmPin,  amplup);
  }               // and here the ramp is generated

  downtime = uppot1 / 5;                          //this sets the downslope length relative to the upslope

  deltatime = (T - uppot1);                       //this creates a new clock, starting at the top of the ramp

  ampldown = (samplup * (downtime - deltatime)) / downtime; //this line describes the downslope, relative to deltatime

  if (T > uppot1 && T < uppot1 + downtime)        // this line defines the down ramp time interval
  {

    analogWrite (pwmPin, ampldown  );                       // and here the downslope is generated
  }

  if ( T >= uppot1 + downtime )         //this defines interval between ramps
  {

    analogWrite (pwmPin, 0);            //rampsignal set to zero (buckconverter idling)
  }
  if ( T >= uppot1 + downtime + 600 )   // The UD2.7 pulse is delayed 600uS to allow ramp low pass filter to settle to 0
  {

    digitalWrite (pulsePin, LOW);       //signal to UD2.7C is terminated

    delay (BPSpot);                     //this sets the repetition rate between ramps

    nowtime = micros();                  //updating time operator, for loop clock reset

    return true;

  }

  return false;
}

The 'static' keyword means that the variable remembers its value between calls to the function. It's like a global variable from that perspective but only the function can touch it.

The button press now only sets the flag to false. Next time loop() is executed, it will see this and call ramp() and update the fRampCompleted. The state of the button is now irrelevant because ramp() keeps on being called till it returns true.

When it returns true, the state of the button is relevant again; so if you keep the button pressed, fRampCompleted will be set to false again and the next iteration ramp() will be called again. If the button however is no longer pressed, fRampCompleted will stay true and successive calls to loop() will NOT call ramp() again.

PS
I can't compile your code as I don't know the functions 'analogWriteResolution()' and 'analogReadResolution()'; which board are you using?

sterretje,

I thank you from my heart, I just tested the code here before going to the day job, and it works wonderfully!

I hope to understand the code later today.

The board is an Arduino UNO, which I use because it is straightforward to set the pwm frequency on it, by editing it's variant.h file.

Thank you very much, have a happy weekend, and unless you protest, I will put a credit note to your work in the header of the file.
Something like:

Sterretje on the Arduino Forum solved the problem of controlling ramp() from inside loop()

It will be widely used by Tesla Coil Experimenters around the globe, because I always offer my own work to the public domain.

Thanks again,and

Cheers, Finn Hammer

You should actually get rid of the delay in the last timing 'if' and use an approach as with all the other timing 'ifs'.

We can discuss that after the weekend if you are interested. I can also help you (if needed) to understand the code in more detail.

You're welcome to add a credit in the line of
"Thanks to sterretje on arduinoforums for assisting in fixing a timing issue"

Hey Finn.

My question is.
Why dont you use a for loop for the generation of the ramp.

That way the forloop has to complete before the processor will see the switch has been released.

I use for loops for my ramp generator and they work good.

Greetigs jeroen

I hope that the OP got the project working in the 11 months or so since the original question.