Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

is there an issue in HW_pwm on the ESP8266? #2888

Closed
pljakobs opened this issue Oct 17, 2024 · 8 comments
Closed

is there an issue in HW_pwm on the ESP8266? #2888

pljakobs opened this issue Oct 17, 2024 · 8 comments
Labels

Comments

@pljakobs
Copy link
Contributor

maybe just a sanity check:

I noticed that my LED controllers are stuck and the LED output doesn't change anymore.
I dug deep in my code but could not really find anything wrong - today, I compiled the Basic_PWM example, changed the pins to match my layout (but also tried it on a naked chip in a programmer) and while I could get the on-chip LED to dim up and down nicely, it seemed that none of the external pins did (tried 4, 5, 12, 13 and 14).
I checked with a scope and could see GPIO2 PWM'ing nicely but none of the others.

Looking at the HardwarePWM.cpp module, I can't see anything out of the ordinary there. I have tested the same hardware with a simple Arduino sketch driving the PWM pins using analogWrite and they work fine.

Could someone be so kind and double check this? I feel slightly insane right now.

Why would GPIO2 work and the others would not?

@pljakobs
Copy link
Contributor Author

for completeness: this is my modified Basic_HardwarePWM

/*
 * File: Esp SDK Hardware PWM demo
 * Original Author: https://github.com/hrsavla
 *
 * This HardwarePWM library enables Sming framework user to use ESP SDK PWM API
 * Period of PWM is fixed to 1000us / Frequency = 1khz
 * Duty at 100% = 22222. Duty at 0% = 0
 * You can use function setPeriod() to change frequency/period.
 * Calculate the Duty as per the formulae give in ESP8266 SDK
 * Duty = (Period *1000)/45
 *
 * PWM can be generated on up to 8 pins (ie All pins except pin 16)
 * Created on August 17, 2015, 2:27 PM
 *
 * See also ESP8266 Technical Reference, Chapter 12:
 * http://espressif.com/sites/default/files/documentation/esp8266-technical_reference_en.pdf
 */
#include <SmingCore.h>
#include <HardwarePWM.h>

#define LED_PIN 2

namespace
{
// List of pins that you want to connect to pwm
uint8_t pins[]{
	13,12,14,5,4,LED_PIN
};
HardwarePWM HW_pwm(pins, ARRAY_SIZE(pins));

SimpleTimer procTimer;

const int maxDuty = HW_pwm.getMaxDuty();

[[ __maybe_unused__ ]]void doPWM()
{
	static bool countUp = true;
	static int duty;
  static int c;

	const int increment = maxDuty / 50;

	if(countUp) {
		duty += increment;
    debug_i("duty %i", duty);
		if(duty >= maxDuty) {
			duty = maxDuty;
			countUp = false;
		}
	} else {
		duty -= increment;
    debug_i("duty %i", duty);
		if(duty <= 0) {
			duty = 0;
			countUp = true;
      c++;
      debug_i("channel: %i", pins[c]);
      if(c>sizeof(pins)){
        c=0;
      }
		}
	}
    HW_pwm.analogWrite(pins[c], duty);
}

} // namespace

void init()
{
	Serial.begin(SERIAL_BAUD_RATE); // 115200 by default
	Serial.systemDebugOutput(true); // Enable debug output to serial

	// WIFI not needed for demo. So disabling WIFI.
#ifndef DISABLE_WIFI
	WifiStation.enable(false);
	WifiAccessPoint.enable(false);
#endif

	// Setting PWM values on 8 different pins
	HW_pwm.analogWrite(4, maxDuty);
	HW_pwm.analogWrite(5, maxDuty / 2);
	HW_pwm.analogWrite(0, maxDuty / 3);
	HW_pwm.analogWrite(2, maxDuty / 4);
	HW_pwm.analogWrite(15, maxDuty / 5);
	HW_pwm.analogWrite(13, maxDuty / 6);
	HW_pwm.analogWrite(12, maxDuty / 7);
	HW_pwm.analogWrite(14, maxDuty / 8);

	Serial.println(_F("PWM output set on all 8 Pins. Kindly check...\r\n"
					  "Now LED_PIN will go from 0 to VCC to 0 in cycles."));
	procTimer.initializeMs<100>(doPWM).start();
}

and this is the Arduino sketch:

#define LED_PIN 2
uint8_t pins[]={13,12,14,5,4,LED_PIN};

void setup() {
  Serial.begin(115200);
  for(int i=0;i<sizeof(pins);i++){
    pinMode(pins[i], OUTPUT);
    analogWrite(pins[i],0);
  }
  Serial.printf("Channel: 0");
}

void loop() {
  static bool countUp=true;
  static int duty;
  static int v,c;
  delay(10);
  if(countUp){
    analogWrite(pins[c], v);
    v++;
    if(v==255)
      countUp=false; 
  } else {
    analogWrite(pins[c], v);
    v--;
    if(v==0){
      countUp=true;
      c++;
      if(c>sizeof(pins))
        c=0;
        Serial.printf("channel: %i",pins[c]);
    }
  }
  Serial.printf("v: %i\n",v);
}

With Arduino, I get nice fading of five+1 channels, with Sming HardwarePWM, not so much.
Since I can't see anything wrong with the HardwarePWM module, I suspect it might be the underlying espressif code?

@pljakobs
Copy link
Contributor Author

pljakobs commented Oct 17, 2024

confusing, if I add this line:

    debug_i("channel %i, set duty %i, get duty %i \n", pins[c], duty, pwm_get_duty(pins[c]));

I get zero duty for all channels but 2 and 5,

94157833 channel 14, set duty 20500, get duty 0
94257833 channel 14, set duty 21000, get duty 0
94357833 channel 14, set duty 21500, get duty 0
94457833 channel 14, set duty 22000, get duty 0
94557833 channel 14, set duty 22500, get duty 0
94657833 channel 14, set duty 23000, get duty 0
94757833 channel 14, set duty 23500, get duty 0
94857833 channel 14, set duty 24000, get duty 0

5 is stuck at 500:

109757833 channel 5, set duty 1500, get duty 500
109857833 channel 5, set duty 1000, get duty 500
109957833 channel 5, set duty 500, get duty 500
110057833 channel 5, set duty 0, get duty 500

and 2, the LED_BUILTIN works as expected:

110257833 channel 4, set duty 1000, get duty 500
110357833 channel 4, set duty 1500, get duty 1000
110457833 channel 4, set duty 2000, get duty 1500
110557833 channel 4, set duty 2500, get duty 2000
110657833 channel 4, set duty 3000, get duty 2500
110757833 channel 4, set duty 3500, get duty 3000
110857833 channel 4, set duty 4000, get duty 3500
110957833 channel 4, set duty 4500, get duty 4000
111057833 channel 4, set duty 5000, get duty 4500

[edit: just noticed that this is out of sync, that's before the debug line is before the setDuty line in the code, so it always shows the next to be set but the current set. The results are as expected, though]

Since the same code is executed for all pins, I can only think there's something wrong with the underlying configuration of the pins / pwm channels.

At least, I feel that I might not be making some very stupid mistake here. I hope.

@pljakobs
Copy link
Contributor Author

this is with ENABLE_CUSTOM_PWM=1 btw. I'm still thinking I may be missing something here, after all, esp nonos has not been changed in a long while.

@pljakobs
Copy link
Contributor Author

pljakobs commented Oct 17, 2024

really? This one drove me mad! I thought I had messed something up when moving to ConfigDB!
It has been in since April? I usually test on a dev board, and since the pwm part has always worked, I never bothered to check until I thought I'd update one of my light fixtures in the house.
Thank you for the quick turnaround - testing now.

@pljakobs
Copy link
Contributor Author

hmm... seemed to work with the example I built but not with the full firmware yet. Will examine tomorro.

@mikee47 mikee47 added the Bug label Oct 18, 2024
slaff pushed a commit that referenced this issue Oct 18, 2024
Fix bug introduced in #2752 where PWM doesn't initialise GPIO correctly. See #2888.
@slaff
Copy link
Contributor

slaff commented Oct 18, 2024

@pljakobs can you get the latest Sming version and check if the fix is working for you?

@pljakobs
Copy link
Contributor Author

I'm testing, it does work for Basic_HwPWM, so I assume it fixes the bug.
It does not seem to work for my esp_rgbww firmware, which surprises me.

@pljakobs
Copy link
Contributor Author

confirmed fixed, I had another issue in my own code that also made PWM not work. Thank you both!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants