espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
13.63k stars 7.41k forks source link

Proposal for analogWrite implementation #849

Closed bmitov closed 5 years ago

bmitov commented 6 years ago

Hi everyone,

I am experimenting with this simple implementation for analogWrite. Please let me know what you think? For now I am adding it as a temporary solution in the Visuino libraries, until official support is implemented. Please feel free to use it in any way you want and include it or something similar in the ESP32 libraries.

Code:


namespace Mitov
{
    uint8_t CESP32PWMTimers[ 2 ] = {0};
    uint8_t CESP32PWMPinMap[ 40 ] = {0};
}
    void analogWrite( uint8_t APin, uint16_t AValue )
    {
//      Serial.println( "analogWrite" );
//      Serial.println( AValue );
        if( AValue == 0 || AValue == 255 )
        {
            if( Mitov::CESP32PWMPinMap[ APin ] != 0 )
            {
                ledcWrite( Mitov::CESP32PWMPinMap[ APin ] - 1, AValue );
//              Serial.println( "ledcDetachPin" );
                digitalWrite( APin, (AValue == 255 ) ? HIGH : LOW );
                ledcDetachPin( APin );
                uint8_t AChannel = Mitov::CESP32PWMPinMap[ APin ] - 1;
                Mitov::CESP32PWMTimers[ AChannel >> 3 ] &= ~ ( 1 << ( AChannel & 7 ) );
                Mitov::CESP32PWMPinMap[ APin ] = 0;
            }

            digitalWrite( APin, (AValue == 255 ) ? HIGH : LOW );
            return;
        }

        if( Mitov::CESP32PWMPinMap[ APin ] == 0 )
        {
            uint8_t AChannel = 0;
            for( AChannel = 0; AChannel < 16; ++AChannel )
                if( ! ( Mitov::CESP32PWMTimers[ AChannel >> 3 ] & ( 1 << ( AChannel & 7 ) ) ))
                    break;

            if( AChannel == 16 )
                return; // Can't allocate channel

            Mitov::CESP32PWMPinMap[ APin ] = AChannel + 1;
            Mitov::CESP32PWMTimers[ AChannel >> 3 ] != ( 1 << ( AChannel & 7 ) );
            ledcSetup( AChannel, 1000, 8 ); // 1KHz 8 bit
            ledcWrite( AChannel, AValue );
            ledcAttachPin( APin, AChannel );
//          Serial.print( "ledcAttachPin: " ); Serial.print( APin ); Serial.print( " " ); Serial.println( AChannel );
            return;
        }

        ledcWrite( Mitov::CESP32PWMPinMap[ APin ] - 1, AValue );
//      Serial.print( "ledcWrite: " ); Serial.print( Mitov::CESP32PWMPinMap[ APin ] - 1 ); Serial.print( " " ); Serial.println( AValue );
    }
imayoda commented 6 years ago

nice abstraction :)

bmitov commented 6 years ago

Thank you imayoda! :-) I think it maybe better to implement it with Sigma/Delta. Is there any documentation or explanation on the Sigma/Delta values?

imayoda commented 6 years ago

hasn't read more than this on the argument, still waiting for my first esp32 breakouts to come :) https://esp-idf.readthedocs.io/en/v2.0/api/peripherals/sigmadelta.html kudos

arthurzennig commented 6 years ago

Hi Mitov, your implementation works just fine!

bmitov commented 6 years ago

Thank you arthurzennig, I showed it here as proposal to be included in the official library. I would also appreciate any suggestions for improvements. For now this is what I use in the Visuino support for ESP32. Cheers, Boian

erropix commented 6 years ago

Hi @bmitov

I have create a small library that provide the classic analogWrite for ESP32, please test it and give me your feedback

Repository https://github.com/ERROPiX/ESP32_AnalogWrite

bmitov commented 6 years ago

Thank you ERROPiX, Looks good :-) . Seems like you are using some ideas similar to my implementation :-)

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] commented 5 years ago

This stale issue has been automatically closed. Thank you for your contributions.