PWM control



  • Hello everyone,

    The aim here is to control the speed of a 5v fan with PWM of an arduino nano.
    I usualy do it with this code:

    const byte OC1A_PIN = 9;
    const byte OC1B_PIN = 10;
    
    const word PWM_FREQ_HZ = 25000; //Adjust this value to adjust the frequency
    const word TCNT1_TOP = 16000000/(2*PWM_FREQ_HZ);
    
    byte in = 0;
    
    void setup() {
      
      pinMode(OC1A_PIN, OUTPUT);
      Serial.begin(9600);
      Serial.println("Demarage du PWM"); // so I can keep track of what is loaded
     
    
    
      // Clear Timer1 control and count registers
      TCCR1A = 0;
      TCCR1B = 0;
      TCNT1  = 0;
    
      // Set Timer1 configuration
      // COM1A(1:0) = 0b10   (Output A clear rising/set falling)
      // COM1B(1:0) = 0b00   (Output B normal operation)
      // WGM(13:10) = 0b1010 (Phase correct PWM)
      // ICNC1      = 0b0    (Input capture noise canceler disabled)
      // ICES1      = 0b0    (Input capture edge select disabled)
      // CS(12:10)  = 0b001  (Input clock select = clock/1)
      
      TCCR1A |= (1 << COM1A1) | (1 << WGM11);
      TCCR1B |= (1 << WGM13) | (1 << CS10);
      ICR1 = TCNT1_TOP;
    }
    
    void loop() {
    if (Serial.available()) {       // Check if there's data
        char buf[10];
        int in = Serial.readBytesUntil('\n', buf, sizeof buf - 1);
        buf[in]=0;
        in = atoi(buf);
        if (in > 100)
          in = 100;
        Serial.println(in);// Pass the value of "in" to the pin}
        setPwmDuty(in); //Change this value 0-100 to adjust duty cycle
    }
    }
    void setPwmDuty(byte duty) {
      OCR1A = (word) (duty*TCNT1_TOP)/100;
    }
    

    Is it possible to do the same with mysensors?

    The next step of this would be to connect the arduino via USB and control it using domoticz.


  • Mod

    @Dovane-Benattar ofcourse! All the initialization and pwm setting code should be copied to the mysensors sketch, and the serial reading could be replaced by mysensors message handling.



  • Thanks Yveaux! I will give it a try like this



  • @Yveaux thank you for your answer!

    /**
    * The MySensors Arduino library handles the wireless radio link and protocol
    * between your home built sensors/actuators and HA controller of choice.
    * The sensors forms a self healing radio network with optional repeaters. Each
    * repeater and gateway builds a routing tables in EEPROM which keeps track of the
    * network topology allowing messages to be routed to nodes.
    *
    * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
    * Copyright (C) 2013-2018 Sensnology AB
    * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
    *
    * Documentation: http://www.mysensors.org
    * Support Forum: http://forum.mysensors.org
    *
    * This program is free software; you can redistribute it and/or
    * modify it under the terms of the GNU General Public License
    * version 2 as published by the Free Software Foundation.
    *
    *******************************
    *
    * DESCRIPTION
    * The ArduinoGateway prints data received from sensors on the serial link.
    * The gateway accepts input on serial which will be sent out on radio network.
    *
    * The GW code is designed for Arduino Nano 328p / 16MHz
    *
    * Wire connections (OPTIONAL):
    * - Inclusion button should be connected between digital pin 3 and GND
    * - RX/TX/ERR leds need to be connected between +5V (anode) and digital pin 6/5/4 with resistor 270-330R in a series
    *
    * LEDs (OPTIONAL):
    * - To use the feature, uncomment any of the MY_DEFAULT_xx_LED_PINs
    * - RX (green) - blink fast on radio message received. In inclusion mode will blink fast only on presentation received
    * - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly
    * - ERR (red) - fast blink on error during transmission error or receive crc error
    *
    */
    
    // Enable debug prints to serial monitor
    #define MY_DEBUG
    
    
    // Enable and select radio type attached
    #define MY_RADIO_RF24
    //#define MY_RADIO_NRF5_ESB
    //#define MY_RADIO_RFM69
    //#define MY_RADIO_RFM95
    
    // Set LOW transmit power level as default, if you have an amplified NRF-module and
    // power your radio separately with a good regulator you can turn up PA level.
    #define MY_RF24_PA_LEVEL RF24_PA_LOW
    
    // Enable serial gateway
    #define MY_GATEWAY_SERIAL
    
    // Define a lower baud rate for Arduinos running on 8 MHz (Arduino Pro Mini 3.3V & SenseBender)
    #if F_CPU == 8000000L
    #define MY_BAUD_RATE 38400
    #endif
    
    // Enable inclusion mode
    #define MY_INCLUSION_MODE_FEATURE
    // Enable Inclusion mode button on gateway
    //#define MY_INCLUSION_BUTTON_FEATURE
    
    // Inverses behavior of inclusion button (if using external pullup)
    //#define MY_INCLUSION_BUTTON_EXTERNAL_PULLUP
    
    // Set inclusion mode duration (in seconds)
    #define MY_INCLUSION_MODE_DURATION 60
    // Digital pin used for inclusion mode button
    //#define MY_INCLUSION_MODE_BUTTON_PIN  3
    
    // Set blinking period
    #define MY_DEFAULT_LED_BLINK_PERIOD 300
    
    // Inverses the behavior of leds
    //#define MY_WITH_LEDS_BLINKING_INVERSE
    
    // Flash leds on rx/tx/err
    // Uncomment to override default HW configurations
    //#define MY_DEFAULT_ERR_LED_PIN 4  // Error led pin
    //#define MY_DEFAULT_RX_LED_PIN  6  // Receive led pin
    //#define MY_DEFAULT_TX_LED_PIN  5  // the PCB, on board LED
    
    #include <MySensors.h>
    
    const byte OC1A_PIN = 9;
    const byte OC1B_PIN = 10;
    
    const word PWM_FREQ_HZ = 25000; //Adjust this value to adjust the frequency
    const word TCNT1_TOP = 16000000/(2*PWM_FREQ_HZ);
    
    byte in = 0;
    
    void setup()
    {
    	// Setup locally attached sensors
     pinMode(OC1A_PIN, OUTPUT);
      Serial.begin(9600);
      Serial.print(0);
      
    
    
      // Clear Timer1 control and count registers
      TCCR1A = 0;
      TCCR1B = 0;
      TCNT1  = 0;
    
      // Set Timer1 configuration
      // COM1A(1:0) = 0b10   (Output A clear rising/set falling)
      // COM1B(1:0) = 0b00   (Output B normal operation)
      // WGM(13:10) = 0b1010 (Phase correct PWM)
      // ICNC1      = 0b0    (Input capture noise canceler disabled)
      // ICES1      = 0b0    (Input capture edge select disabled)
      // CS(12:10)  = 0b001  (Input clock select = clock/1)
      
      TCCR1A |= (1 << COM1A1) | (1 << WGM11);
      TCCR1B |= (1 << WGM13) | (1 << CS10);
      ICR1 = TCNT1_TOP;
    
    
    }
    
    void presentation()
    {
    	// Present locally attached sensors
    }
    
    void loop()
    {
    	// Send locally attached sensor data here
     if (Serial.available()) {       // Check if there's data
        char buf[10];
        int in = Serial.readBytesUntil('\n', buf, sizeof buf - 1);
        buf[in]=0;
        in = atoi(buf);
        if (in >= 100)
          in = 100;
        Serial.println(in);// Pass the value of "in" to the pin}
        setPwmDuty(in); //Change this value 0-100 to adjust duty cycle
    }
    }
    void setPwmDuty(byte duty) {
      OCR1A = (word) (duty*TCNT1_TOP)/100;
    }
    
    

    Can you tell me if this could work? (I tried but it does not.. maybe I do something else wrong)



  • Some news, it works now!
    I took some code for a dimmable LED here

    The only problem now is that the fan does a little sound it didn't with the first code.

    here is the code:

    /**
    * The MySensors Arduino library handles the wireless radio link and protocol
    * between your home built sensors/actuators and HA controller of choice.
    * The sensors forms a self healing radio network with optional repeaters. Each
    * repeater and gateway builds a routing tables in EEPROM which keeps track of the
    * network topology allowing messages to be routed to nodes.
    *
    * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
    * Copyright (C) 2013-2019 Sensnology AB
    * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
    *
    * Documentation: http://www.mysensors.org
    * Support Forum: http://forum.mysensors.org
    *
    * This program is free software; you can redistribute it and/or
    * modify it under the terms of the GNU General Public License
    * version 2 as published by the Free Software Foundation.
    *
    *******************************
    *
    * DESCRIPTION
    * The ArduinoGateway prints data received from sensors on the serial link.
    * The gateway accepts input on serial which will be sent out on radio network.
    *
    * The GW code is designed for Arduino Nano 328p / 16MHz
    *
    * Wire connections (OPTIONAL):
    * - Inclusion button should be connected between digital pin 3 and GND
    * - RX/TX/ERR leds need to be connected between +5V (anode) and digital pin 6/5/4 with resistor 270-330R in a series
    *
    * LEDs (OPTIONAL):
    * - To use the feature, uncomment any of the MY_DEFAULT_xx_LED_PINs
    * - RX (green) - blink fast on radio message received. In inclusion mode will blink fast only on presentation received
    * - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly
    * - ERR (red) - fast blink on error during transmission error or receive crc error
    *
    */
    
    // Enable debug prints to serial monitor
    #define MY_DEBUG
    
    
    // Enable and select radio type attached
    //#define MY_RADIO_RF24
    //#define MY_RADIO_NRF5_ESB
    //#define MY_RADIO_RFM69
    //#define MY_RADIO_RFM95
    
    // Set LOW transmit power level as default, if you have an amplified NRF-module and
    // power your radio separately with a good regulator you can turn up PA level.
    //#define MY_RF24_PA_LEVEL RF24_PA_LOW
    
    // Enable serial gateway
    #define MY_GATEWAY_SERIAL
    
    // Define a lower baud rate for Arduinos running on 8 MHz (Arduino Pro Mini 3.3V & SenseBender)
    #if F_CPU == 8000000L
    #define MY_BAUD_RATE 38400
    #endif
    
    // Enable inclusion mode
    #define MY_INCLUSION_MODE_FEATURE
    // Enable Inclusion mode button on gateway
    //#define MY_INCLUSION_BUTTON_FEATURE
    
    // Inverses behavior of inclusion button (if using external pullup)
    //#define MY_INCLUSION_BUTTON_EXTERNAL_PULLUP
    
    // Set inclusion mode duration (in seconds)
    #define MY_INCLUSION_MODE_DURATION 60
    // Digital pin used for inclusion mode button
    //#define MY_INCLUSION_MODE_BUTTON_PIN  3
    
    // Set blinking period
    #define MY_DEFAULT_LED_BLINK_PERIOD 300
    
    // Inverses the behavior of leds
    //#define MY_WITH_LEDS_BLINKING_INVERSE
    
    // Flash leds on rx/tx/err
    // Uncomment to override default HW configurations
    //#define MY_DEFAULT_ERR_LED_PIN 4  // Error led pin
    //#define MY_DEFAULT_RX_LED_PIN  6  // Receive led pin
    //#define MY_DEFAULT_TX_LED_PIN  5  // the PCB, on board LED
    
    #include <MySensors.h>
    
    #define SN "DimmableLED"
    #define SV "1.1"
    
    #define LED_PIN 9      // Arduino pin attached to MOSFET Gate pin
    #define FADE_DELAY 10  // Delay in ms for each percentage fade up/down (10ms = 1s full-range dim)
    
    static int16_t currentLevel = 0;  // Current dim level...
    MyMessage dimmerMsg(0, V_DIMMER);
    MyMessage lightMsg(0, V_LIGHT);
    
    void setup()
    {
    	// Setup locally attached sensors
     request( 0, V_DIMMER );
    }
    
    void presentation()
    {
    	// Present locally attached sensors
     present( 0, S_DIMMER );
    
        sendSketchInfo(SN, SV);
    }
    
    void loop()
    {
    	// Send locally attached sensor data here
    }
    
    void receive(const MyMessage &message)
    {
        if (message.getType() == V_LIGHT || message.getType() == V_DIMMER) {
    
            //  Retrieve the power or dim level from the incoming request message
            int requestedLevel = atoi( message.data );
    
            // Adjust incoming level if this is a V_LIGHT variable update [0 == off, 1 == on]
            requestedLevel *= ( message.getType() == V_LIGHT ? 100 : 1 );
    
            // Clip incoming level to valid range of 0 to 100
            requestedLevel = requestedLevel > 100 ? 100 : requestedLevel;
            requestedLevel = requestedLevel < 0   ? 0   : requestedLevel;
    
            Serial.print( "Changing level to " );
            Serial.print( requestedLevel );
            Serial.print( ", from " );
            Serial.println( currentLevel );
    
            fadeToLevel( requestedLevel );
    
            // Inform the gateway of the current DimmableLED's SwitchPower1 and LoadLevelStatus value...
            send(lightMsg.set(currentLevel > 0));
    
            // hek comment: Is this really nessesary?
            send( dimmerMsg.set(currentLevel) );
    
    
        }
    }
    
    /***
     *  This method provides a graceful fade up/down effect
     */
    void fadeToLevel( int toLevel )
    {
    
        int delta = ( toLevel - currentLevel ) < 0 ? -1 : 1;
    
        while ( currentLevel != toLevel ) {
            currentLevel += delta;
            analogWrite( LED_PIN, (int)(currentLevel / 100. * 255) );
            delay( FADE_DELAY );
        }
    }
    

    Do you have any idea why it does this?


  • Hardware Contributor

    @doodoovane
    not sure if I get it, but the little sound could be generated by pwm freq.

    Note, your last sketch is not ideal:

    • don't send msg in receive(). it's better to update a variable, and check this variable in loop() for sending a msg, to avoid recursive call to receive()
    • Same for your fading function, it's better to call it from loop(). Receive() should finish as fast as possible.
    • don't use delay() in your fading function, it's a blocking function. It's better to do this async, in a non-blocking way, or use wait() as it can process received msg in background .

  • Mod

    @scalz the delay() and send() calls are from the MySensors example, my guess is that doodoovane just followed the example.


  • Hardware Contributor

    @mfalkvidd
    yep I noticed that. I just provided a few feedbacks for his future sketches 🙂



  • @scalz that's what I thought but it doesn't make any sound with the first code I posted.
    Something to do with the frequency maybe?



  • This post is deleted!


  • Me again!
    So the problem seemed to be the frequency as I don't have sound anymore.
    With a little hindsight, I looked back at @Yveaux's messages (here and on another post) and here is what I've tried.

    /**
    * The MySensors Arduino library handles the wireless radio link and protocol
    * between your home built sensors/actuators and HA controller of choice.
    * The sensors forms a self healing radio network with optional repeaters. Each
    * repeater and gateway builds a routing tables in EEPROM which keeps track of the
    * network topology allowing messages to be routed to nodes.
    *
    * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
    * Copyright (C) 2013-2019 Sensnology AB
    * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
    *
    * Documentation: http://www.mysensors.org
    * Support Forum: http://forum.mysensors.org
    *
    * This program is free software; you can redistribute it and/or
    * modify it under the terms of the GNU General Public License
    * version 2 as published by the Free Software Foundation.
    *
    *******************************
    *
    * DESCRIPTION
    * The ArduinoGateway prints data received from sensors on the serial link.
    * The gateway accepts input on serial which will be sent out on radio network.
    *
    * The GW code is designed for Arduino Nano 328p / 16MHz
    *
    * Wire connections (OPTIONAL):
    * - Inclusion button should be connected between digital pin 3 and GND
    * - RX/TX/ERR leds need to be connected between +5V (anode) and digital pin 6/5/4 with resistor 270-330R in a series
    *
    * LEDs (OPTIONAL):
    * - To use the feature, uncomment any of the MY_DEFAULT_xx_LED_PINs
    * - RX (green) - blink fast on radio message received. In inclusion mode will blink fast only on presentation received
    * - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly
    * - ERR (red) - fast blink on error during transmission error or receive crc error
    *
    */
    
    // Enable debug prints to serial monitor
    #define MY_DEBUG
    
    
    // Enable and select radio type attached
    //#define MY_RADIO_RF24
    //#define MY_RADIO_NRF5_ESB
    //#define MY_RADIO_RFM69
    //#define MY_RADIO_RFM95
    
    // Set LOW transmit power level as default, if you have an amplified NRF-module and
    // power your radio separately with a good regulator you can turn up PA level.
    //#define MY_RF24_PA_LEVEL RF24_PA_LOW
    
    // Enable serial gateway
    #define MY_GATEWAY_SERIAL
    
    // Define a lower baud rate for Arduinos running on 8 MHz (Arduino Pro Mini 3.3V & SenseBender)
    #if F_CPU == 8000000L
    #define MY_BAUD_RATE 38400
    #endif
    
    // Enable inclusion mode
    #define MY_INCLUSION_MODE_FEATURE
    // Enable Inclusion mode button on gateway
    //#define MY_INCLUSION_BUTTON_FEATURE
    
    // Inverses behavior of inclusion button (if using external pullup)
    //#define MY_INCLUSION_BUTTON_EXTERNAL_PULLUP
    
    // Set inclusion mode duration (in seconds)
    #define MY_INCLUSION_MODE_DURATION 60
    // Digital pin used for inclusion mode button
    //#define MY_INCLUSION_MODE_BUTTON_PIN  3
    
    // Set blinking period
    #define MY_DEFAULT_LED_BLINK_PERIOD 300
    
    // Inverses the behavior of leds
    //#define MY_WITH_LEDS_BLINKING_INVERSE
    
    // Flash leds on rx/tx/err
    // Uncomment to override default HW configurations
    //#define MY_DEFAULT_ERR_LED_PIN 4  // Error led pin
    //#define MY_DEFAULT_RX_LED_PIN  6  // Receive led pin
    //#define MY_DEFAULT_TX_LED_PIN  5  // the PCB, on board LED
    
    #include <MySensors.h>
    #include <TimerOne.h>
    
    #define SN "DimmableLED"
    #define SV "1.1"
    
    #define LED_PIN 9      // Arduino pin attached to MOSFET Gate pin
    #define FADE_DELAY 10  // Delay in ms for each percentage fade up/down (10ms = 1s full-range dim)
    
    
    static int16_t currentLevel = 0;  // Current dim level...
    MyMessage dimmerMsg(0, V_DIMMER);
    MyMessage lightMsg(0, V_LIGHT);
    
    void setup()
    {
      // Setup locally attached sensors
     request( 0, V_DIMMER );
     #define PWM_FREQ_HZ (25000) 
    #define PWM_CYCLE_US (1000000/PWM_FREQ_HZ)
    
    Timer1.initialize(PWM_CYCLE_US);
    Timer1.pwm(LED_PIN, 1023); 
    }
    
    void presentation()
    {
      // Present locally attached sensors
     present( 0, S_DIMMER );
    
        sendSketchInfo(SN, SV);
    }
    
    void loop()
    {
      // Send locally attached sensor data here
    }
    
    void receive(const MyMessage &message)
    {
        if (message.getType() == V_LIGHT || message.getType() == V_DIMMER) {
    
            //  Retrieve the power or dim level from the incoming request message
            int requestedLevel = atoi( message.data );
    
            // Adjust incoming level if this is a V_LIGHT variable update [0 == off, 1 == on]
            requestedLevel *= ( message.getType() == V_LIGHT ? 100 : 1 );
    
            // Clip incoming level to valid range of 0 to 100
            requestedLevel = requestedLevel >= 101 ? 100 : requestedLevel;
            requestedLevel = requestedLevel < 0   ? 0   : requestedLevel;
    
            Serial.print( "Changing level to " );
            Serial.print( requestedLevel );
            Serial.print( ", from " );
            Serial.println( currentLevel );
    
            fadeToLevel( requestedLevel );
    
            // Inform the gateway of the current DimmableLED's SwitchPower1 and LoadLevelStatus value...
            send(lightMsg.set(currentLevel > 0));
    
            // hek comment: Is this really nessesary?
            send( dimmerMsg.set(currentLevel) );
    
    
        }
    }
    
    /***
     *  This method provides a graceful fade up/down effect
     */
    void fadeToLevel( int toLevel )
    {
    
        int delta = ( toLevel - currentLevel ) < 0 ? -1 : 1;
    
        while ( currentLevel != toLevel ) {
            currentLevel += delta;
            analogWrite( LED_PIN, (int)(currentLevel / 100. * 255) );
            delay( FADE_DELAY );
        }
    }
    

    No more sound, but now Can't get it more than 99% in domoticz... The only way to get 100% is to turn it off and turn it back on. As long as you touch the slider, no more 100%...

    Any clue of what can cause this?


  • Mod

    @doodoovane why do you use analogwrite instead of Timer1.setPwmDuty?
    Also, the fading should not be required for a fan.
    Iirr the maximum duty value is 1023. Likely the fan won't be at its maximum speed then, only when you supply it a continuous high 'pulse'. Is that what you mean by 99%?



  • @Yveaux said in PWM control:

    Timer1.setPwmDuty

    I did but there must be something wrong with my code as the PWM doesn't work anymore.
    Here is my try:

    #include <MySensors.h>
    #include <TimerOne.h>
    
    #define SN "Fan_PWM"
    #define SV "1.3"
    
    #define LED_PIN 9      // Arduino pin attached to MOSFET Gate pin
    #define FADE_DELAY 10  // Delay in ms for each percentage fade up/down (10ms = 1s full-range dim)
    
    
    static int16_t currentLevel = 0;  // Current dim level...
    MyMessage dimmerMsg(0, V_DIMMER);
    MyMessage lightMsg(0, V_LIGHT);
    
    void setup()
    {
      // Setup locally attached sensors
     request( 0, V_DIMMER );
     #define PWM_FREQ_HZ (25000) 
     #define PWM_CYCLE_US (1000000/PWM_FREQ_HZ)
    
    Timer1.initialize(PWM_CYCLE_US);
    Timer1.pwm(LED_PIN, 1023); 
    }
    
    void presentation()
    {
      // Present locally attached sensors
     present( 0, S_DIMMER );
    
        sendSketchInfo(SN, SV);
    }
    
    void loop()
    {
      // Send locally attached sensor data here
    }
    
    void receive(const MyMessage &message)
    {
        if (message.getType() == V_LIGHT || message.getType() == V_DIMMER) {
    
            //  Retrieve the power or dim level from the incoming request message
            int requestedLevel = atoi( message.data );
    
            // Adjust incoming level if this is a V_LIGHT variable update [0 == off, 1 == on]
            requestedLevel *= ( message.getType() == V_LIGHT ? 100 : 1 );
    
            // Clip incoming level to valid range of 0 to 100
            requestedLevel = requestedLevel > 100 ? 100 : requestedLevel;
            requestedLevel = requestedLevel < 0   ? 0   : requestedLevel;
    
            Serial.print( "Changing level to " );
            Serial.print( requestedLevel );
            Serial.print( ", from " );
            Serial.println( currentLevel );
    
            Timer1.setPwmDuty(LED_PIN, requestedLevel);
    
            // Inform the gateway of the current DimmableLED's SwitchPower1 and LoadLevelStatus value...
            send(lightMsg.set(currentLevel > 0));
    
            // hek comment: Is this really nessesary?
            send( dimmerMsg.set(currentLevel) );
    
    
        }
    }
    

    What I mean by 99% is that the slider of the dimmer when pulled to 100% come back to 99% (as I can see in my switch log) in domoticz. And there is no "100%" input just like if I pulled the slider to 99%...



  • Hello everyone,

    I'm still stuck with my problem as I don't fin any solution.
    Is there a way to say in the code "if level is at 100%, stop the PWM regulation (full power fan)" ?

    Thank you for your help


  • Mod

    @doodoovane you can change

    requestedLevel = requestedLevel > 100 ? 100 : requestedLevel;
    

    to

    requestedLevel = requestedLevel > 98 ? 100 : requestedLevel;
    


  • @mfalkvidd said in PWM control:

    requestedLevel = requestedLevel > 98 ? 100 : requestedLevel;

    Thank You @mfalkvidd it works that way! Domoticz still showing me his 99% but at least the fan is going 100%.

    Thank you for your help, sometime thing can get easier 🙂


Log in to reply
 

Suggested Topics

  • 3
  • 1
  • 8
  • 2
  • 5

14
Online

11.4k
Users

11.1k
Topics

112.7k
Posts