Go Down

Topic: PWM voltage on Mega 2560 analog pins 8-15 using arduino-softpwm library (Read 981 times) previous topic - next topic

Here is the original: github.com/Palatis/arduino-softpwm

Here is it now:
Code: [Select]
/*
  Arduino-SoftPWM: a software PWM library for Arduino
  Copyright 2016, Victor Tseng <palatis@gmail.com>
  All rights reserved.
*/

#include <SoftPWM.h>

SOFTPWM_DEFINE_CHANNEL(22, DDRB, PORTB, PORTB0);  //Arduino pin A8
SOFTPWM_DEFINE_CHANNEL(23, DDRB, PORTB, PORTB5);  //Arduino pin A9
SOFTPWM_DEFINE_CHANNEL(24, DDRC, PORTC, PORTC0);  //Arduino pin A10
SOFTPWM_DEFINE_CHANNEL(25, DDRC, PORTC, PORTC1);  //Arduino pin A11
SOFTPWM_DEFINE_CHANNEL(26, DDRC, PORTC, PORTC2);  //Arduino pin A12
SOFTPWM_DEFINE_CHANNEL(27, DDRC, PORTC, PORTC3);  //Arduino pin A13
SOFTPWM_DEFINE_CHANNEL(28, DDRC, PORTC, PORTC4);  //Arduino pin A14
SOFTPWM_DEFINE_CHANNEL(29, DDRC, PORTC, PORTC5);  //Arduino pin A15

/* Here you make an instance of desired channel counts you want
   with the default 256 PWM levels (0 ~ 255). */
//SOFTPWM_DEFINE_OBJECT(20);

/* Or you can make one with only 100 PWM levels (0 ~ 99).
   By using less PWM levels, you may be able to use higher
   pwm frequencies. */
SOFTPWM_DEFINE_OBJECT_WITH_PWM_LEVELS(20, 100);       

/* If you want to use the SoftPWM object outside where it's defined,
   add the following line to the file. */
//SOFTPWM_DEFINE_EXTERN_OBJECT(16);
SOFTPWM_DEFINE_EXTERN_OBJECT_WITH_PWM_LEVELS(20, 100);

void setup() {
  Serial.begin(19200);

  // begin with 60hz pwm frequency
  Palatis::SoftPWM.begin(60);

  // print interrupt load for diagnostic purposes
  Palatis::SoftPWM.printInterruptLoad();
}

void loop() {
 
      for(int pin = 0; pin < 8; pin++)
        for(int s = 63; s <= 255; s += 64)
          {          // PWM: 255 = 5V
            Palatis::SoftPWM.set(pin, s);     // sweeps 1.24, 2.5, 3.75 & 5 V
            delay(500);
          }
}

I am just trying to output a PWM voltage sweep on non-PWM pins (specifically A8-A15).


What do I need to look into or what should I change?

pert

SOFTPWM_DEFINE_CHANNEL(22, DDRB, PORTB, PORTB0);  //Arduino pin A8
SOFTPWM_DEFINE_CHANNEL(23, DDRB, PORTB, PORTB5);  //Arduino pin A9
SOFTPWM_DEFINE_CHANNEL(24, DDRC, PORTC, PORTC0);  //Arduino pin A10
SOFTPWM_DEFINE_CHANNEL(25, DDRC, PORTC, PORTC1);  //Arduino pin A11
SOFTPWM_DEFINE_CHANNEL(26, DDRC, PORTC, PORTC2);  //Arduino pin A12
SOFTPWM_DEFINE_CHANNEL(27, DDRC, PORTC, PORTC3);  //Arduino pin A13
SOFTPWM_DEFINE_CHANNEL(28, DDRC, PORTC, PORTC4);  //Arduino pin A14
SOFTPWM_DEFINE_CHANNEL(29, DDRC, PORTC, PORTC5);  //Arduino pin A15
Those are the pin mappings for the ATmega328P family. You need to change them to pin mappings for the ATmega2560:
https://www.arduino.cc/en/uploads/Hacking/PinMap2560big.png

I also have a fork of the library that allows you to define channels using Arduino pin numbers instead of needing to look up the correct port/bit mapping:
https://github.com/per1234/PalatisSoftPWM

How do you define channels using Arduino pin numbers?

Is it in the example sketch or here:
github.com/per1234/PalatisSoftPWM/blob/master/PalatisSoftPWM.h#L194

pert

The PalatisSoftPWM_example does demonstrate it. You can also see the implementation in the .h file. Here's how it would be done in your case:
Code: [Select]
SOFTPWM_DEFINE_PINA8_CHANNEL(0);  //Configure Arduino pin A8 as PWM channel 0
SOFTPWM_DEFINE_PINA9_CHANNEL(1);
SOFTPWM_DEFINE_PINA10_CHANNEL(2);
SOFTPWM_DEFINE_PINA11_CHANNEL(3);
SOFTPWM_DEFINE_PINA12_CHANNEL(4);
SOFTPWM_DEFINE_PINA13_CHANNEL(5);
SOFTPWM_DEFINE_PINA14_CHANNEL(6);
SOFTPWM_DEFINE_PINA15_CHANNEL(7);

In the end, it works just the same as the arduino-softpwm library, but this is much more friendly to Arduino users, who are often not familiar with how the port/bit pin mappings work.

So I changed SOFTPWM_DEFINE_OBJECT to 8 (instead of 1)

Code: [Select]
#include <PalatisSoftPWM.h>

SOFTPWM_DEFINE_PINA8_CHANNEL(0);  //Configure Arduino pin A8 as PWM channel 0
SOFTPWM_DEFINE_PINA9_CHANNEL(1);
SOFTPWM_DEFINE_PINA10_CHANNEL(2);
SOFTPWM_DEFINE_PINA11_CHANNEL(3);
SOFTPWM_DEFINE_PINA12_CHANNEL(4);
SOFTPWM_DEFINE_PINA13_CHANNEL(5);
SOFTPWM_DEFINE_PINA14_CHANNEL(6);
SOFTPWM_DEFINE_PINA15_CHANNEL(7);

SOFTPWM_DEFINE_OBJECT(8);

void setup() {
  PalatisSoftPWM.begin(60);  // begin with 60 Hz PWM frequency
}

void loop() {
   for(int pin = 0; pin < 8; pin++)
        for(int s = 63; s <= 255; s += 64)
          {          // PWM: 255 = 5V
            PalatisSoftPWM.set(pin, s);     // sweeps 1.24, 2.5, 3.75 & 5 V
            delay(500);
          }
}


I get these errors with defining the channels:

Code: [Select]
Arduino: 1.8.5 (Windows 7), Board: "Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)"

In file included from sketch\PalatisSoftPWM_example.ino.cpp:1:0:

C:\Users\uraynara\Documents\Arduino\PalatisSoftPWM-master\examples\PalatisSoftPWM_example\PalatisSoftPWM_example.ino: In function 'void {anonymous}::pinModeStatic(uint8_t) [with int channel = 1; uint8_t = unsigned char]':

C:\Users\uraynara\Documents\Arduino\libraries\PalatisSoftPWM-master/PalatisSoftPWM.h:322:79: error: 'DDRK1' was not declared in this scope

 #define SOFTPWM_DEFINE_PIN63_CHANNEL(CHANNEL) SOFTPWM_DEFINE_CHANNEL(CHANNEL, DDRK1, PORTK, PORTK1)

                                                                               ^

C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:113:32: note: in definition of macro 'bitClear'

 #define bitClear(value, bit) ((value) &= ~(1UL << (bit)))

                                ^

C:\Users\uraynara\Documents\Arduino\libraries\PalatisSoftPWM-master/PalatisSoftPWM.h:1215:3: note: in expansion of macro 'SOFTPWM_DEFINE_PINMODE'

   SOFTPWM_DEFINE_PINMODE( CHANNEL, PMODE, PORT, BIT )

   ^

C:\Users\uraynara\Documents\Arduino\libraries\PalatisSoftPWM-master/PalatisSoftPWM.h:322:47: note: in expansion of macro 'SOFTPWM_DEFINE_CHANNEL'

 #define SOFTPWM_DEFINE_PIN63_CHANNEL(CHANNEL) SOFTPWM_DEFINE_CHANNEL(CHANNEL, DDRK1, PORTK, PORTK1)

                                               ^

C:\Users\uraynara\Documents\Arduino\libraries\PalatisSoftPWM-master/PalatisSoftPWM.h:354:47: note: in expansion of macro 'SOFTPWM_DEFINE_PIN63_CHANNEL'

 #define SOFTPWM_DEFINE_PINA9_CHANNEL(CHANNEL) SOFTPWM_DEFINE_PIN63_CHANNEL(CHANNEL)

                                               ^

C:\Users\uraynara\Documents\Arduino\PalatisSoftPWM-master\examples\PalatisSoftPWM_example\PalatisSoftPWM_example.ino:4:1: note: in expansion of macro 'SOFTPWM_DEFINE_PINA9_CHANNEL'

 SOFTPWM_DEFINE_PINA9_CHANNEL(1);

 ^

C:\Users\uraynara\Documents\Arduino\libraries\PalatisSoftPWM-master/PalatisSoftPWM.h:322:79: error: 'DDRK1' was not declared in this scope

 #define SOFTPWM_DEFINE_PIN63_CHANNEL(CHANNEL) SOFTPWM_DEFINE_CHANNEL(CHANNEL, DDRK1, PORTK, PORTK1)

                                                                               ^

C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:113:32: note: in definition of macro 'bitClear'

 #define bitClear(value, bit) ((value) &= ~(1UL << (bit)))

                                ^

C:\Users\uraynara\Documents\Arduino\libraries\PalatisSoftPWM-master/PalatisSoftPWM.h:1215:3: note: in expansion of macro 'SOFTPWM_DEFINE_PINMODE'

   SOFTPWM_DEFINE_PINMODE( CHANNEL, PMODE, PORT, BIT )

   ^

C:\Users\uraynara\Documents\Arduino\libraries\PalatisSoftPWM-master/PalatisSoftPWM.h:322:47: note: in expansion of macro 'SOFTPWM_DEFINE_CHANNEL'

 #define SOFTPWM_DEFINE_PIN63_CHANNEL(CHANNEL) SOFTPWM_DEFINE_CHANNEL(CHANNEL, DDRK1, PORTK, PORTK1)

                                               ^

C:\Users\uraynara\Documents\Arduino\libraries\PalatisSoftPWM-master/PalatisSoftPWM.h:354:47: note: in expansion of macro 'SOFTPWM_DEFINE_PIN63_CHANNEL'

 #define SOFTPWM_DEFINE_PINA9_CHANNEL(CHANNEL) SOFTPWM_DEFINE_PIN63_CHANNEL(CHANNEL)

                                               ^

C:\Users\uraynara\Documents\Arduino\PalatisSoftPWM-master\examples\PalatisSoftPWM_example\PalatisSoftPWM_example.ino:4:1: note: in expansion of macro 'SOFTPWM_DEFINE_PINA9_CHANNEL'

 SOFTPWM_DEFINE_PINA9_CHANNEL(1);

 ^

C:\Users\uraynara\Documents\Arduino\libraries\PalatisSoftPWM-master/PalatisSoftPWM.h:322:79: error: 'DDRK1' was not declared in this scope

 #define SOFTPWM_DEFINE_PIN63_CHANNEL(CHANNEL) SOFTPWM_DEFINE_CHANNEL(CHANNEL, DDRK1, PORTK, PORTK1)

                                                                               ^

C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:112:30: note: in definition of macro 'bitSet'

 #define bitSet(value, bit) ((value) |= (1UL << (bit)))

                              ^

C:\Users\uraynara\Documents\Arduino\libraries\PalatisSoftPWM-master/PalatisSoftPWM.h:1215:3: note: in expansion of macro 'SOFTPWM_DEFINE_PINMODE'

   SOFTPWM_DEFINE_PINMODE( CHANNEL, PMODE, PORT, BIT )

   ^

C:\Users\uraynara\Documents\Arduino\libraries\PalatisSoftPWM-master/PalatisSoftPWM.h:322:47: note: in expansion of macro 'SOFTPWM_DEFINE_CHANNEL'

 #define SOFTPWM_DEFINE_PIN63_CHANNEL(CHANNEL) SOFTPWM_DEFINE_CHANNEL(CHANNEL, DDRK1, PORTK, PORTK1)

                                               ^

C:\Users\uraynara\Documents\Arduino\libraries\PalatisSoftPWM-master/PalatisSoftPWM.h:354:47: note: in expansion of macro 'SOFTPWM_DEFINE_PIN63_CHANNEL'

 #define SOFTPWM_DEFINE_PINA9_CHANNEL(CHANNEL) SOFTPWM_DEFINE_PIN63_CHANNEL(CHANNEL)

                                               ^

C:\Users\uraynara\Documents\Arduino\PalatisSoftPWM-master\examples\PalatisSoftPWM_example\PalatisSoftPWM_example.ino:4:1: note: in expansion of macro 'SOFTPWM_DEFINE_PINA9_CHANNEL'

 SOFTPWM_DEFINE_PINA9_CHANNEL(1);

 ^

exit status 1

Compiles with this:

Code: [Select]
SOFTPWM_DEFINE_PINA8_CHANNEL(0);  //Configure Arduino pin A8 as PWM channel 0
SOFTPWM_DEFINE_PIN23_CHANNEL(1);
SOFTPWM_DEFINE_PIN24_CHANNEL(2);
SOFTPWM_DEFINE_PIN25_CHANNEL(3);
SOFTPWM_DEFINE_PIN26_CHANNEL(4);
SOFTPWM_DEFINE_PIN27_CHANNEL(5);
SOFTPWM_DEFINE_PIN28_CHANNEL(6);
SOFTPWM_DEFINE_PIN29_CHANNEL(7);

UKHeliBob

Quote
I am just trying to output a PWM voltage sweep on non-PWM pins
I assume that you realise that a PWM output is either at 0V or 5V and simply switches between the two values
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

I assume that you realise that a PWM output is either at 0V or 5V and simply switches between the two values
Yes. What does this have to do with the issue? Is it not 0-255 with this program?

Code: [Select]
void loop() {
PalatisSoftPWM.set(0, 255);
//PalatisSoftPWM.set(1, 255);
//PalatisSoftPWM.set(2, 255);
//PalatisSoftPWM.set(3, 255);
//PalatisSoftPWM.set(4, 255);
//PalatisSoftPWM.set(5, 255);
//PalatisSoftPWM.set(6, 255);
//PalatisSoftPWM.set(7, 255);
}

UKHeliBob

Quote
What does this have to do with the issue?
Nothing directly, but you will not get
Quote
a PWM voltage sweep
from an Arduino pin.

Quote
Is it not 0-255 with this program?
Nothing is 0-255 in that program snippet.  Writing 255 to a PWM pin will output 5V
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

pert

Thanks so much for reporting this bug adamaero! It was a typo in the register name in the SOFTPWM_DEFINE_PIN63_CHANNEL macro definition. It should have been DDRK instead of DDRK1. I have fixed this and am working on a new release of the library with the bug fixed right now.

If you want to patch your existing installation of the library, you only need to change line 322 of PalatisSoftPWM.h from:
Code: [Select]
#define SOFTPWM_DEFINE_PIN63_CHANNEL(CHANNEL) SOFTPWM_DEFINE_CHANNEL(CHANNEL, DDRK1, PORTK, PORTK1)

Code: [Select]
#define SOFTPWM_DEFINE_PIN63_CHANNEL(CHANNEL) SOFTPWM_DEFINE_CHANNEL(CHANNEL, DDRK, PORTK, PORTK1)
https://github.com/per1234/PalatisSoftPWM/commit/6a1435c675fb83d217d03fb33c2dc7308fb65286

Otherwise, you can download the library from GitHub and replace your existing installation.

@pert Thanks.

@UKHeliBob Again, I understand PWM. In the original post, I wrote a simple voltage sweep in void loop().

Back to the current issue, why isn't a voltage being output:

Code: [Select]
#include <PalatisSoftPWM.h>

SOFTPWM_DEFINE_PINA8_CHANNEL(0);  //Configure Arduino pin A8 as PWM channel 0
//SOFTPWM_DEFINE_PINA9_CHANNEL(1);
//SOFTPWM_DEFINE_PINA10_CHANNEL(2);
//SOFTPWM_DEFINE_PINA11_CHANNEL(3);
//SOFTPWM_DEFINE_PINA12_CHANNEL(4);
//SOFTPWM_DEFINE_PINA13_CHANNEL(5);
//SOFTPWM_DEFINE_PINA14_CHANNEL(6);
//SOFTPWM_DEFINE_PINA15_CHANNEL(7);

SOFTPWM_DEFINE_OBJECT(8);

void setup() {
  PalatisSoftPWM.begin(60);  // begin with 60 Hz PWM frequency
}

void loop() {
PalatisSoftPWM.set(0, 255);
//PalatisSoftPWM.set(1, 255);
//PalatisSoftPWM.set(2, 255);
//PalatisSoftPWM.set(3, 255);
//PalatisSoftPWM.set(4, 255);
//PalatisSoftPWM.set(5, 255);
//PalatisSoftPWM.set(6, 255);
//PalatisSoftPWM.set(7, 255);
}

UKHeliBob

Please humour me, but how does
Code: [Select]

        for(int s = 63; s <= 255; s += 64)
          {          // PWM: 255 = 5V
            Palatis::SoftPWM.set(pin, s);     // sweeps 1.24, 2.5, 3.75 & 5 V
            delay(500);
          }

output anything other than 0V or 5V ?
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

On a regular PWM pin, the loop does a voltage sweep.

Since the soft PWM program is in bytes, it's not as easy.

UKHeliBob

Quote
On a regular PWM pin, the loop does a voltage sweep.
How are you measuring the voltage ?
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

How are you measuring the voltage ?
DMM. Maybe the fade part of pert's program works like a sweep, if a delay is added...

Go Up