Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
T

tssk

@tssk
About
Posts
51
Topics
5
Shares
0
Groups
0
Followers
0
Following
0

Posts

Recent Best Controversial

  • ArduinoShrink
    T tssk

    Today I came across interesting project https://github.com/nerdralph/ArduinoShrink that promises smaller and faster code for ATmega168 and 328 MCUs at 4 to 16 MHZ.

    But the library is not compatible with mysensors

    wiring.c.o (symbol from plugin): In function `delayMicroseconds':
    (.text+0x0): multiple definition of `main'
    sketch/mys-868-node.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here
    collect2: error: ld returned 1 exit status
    exit status 1
    Error compiling for board Arduino Pro or Pro Mini.
    

    Would it be possible to make it compatible? Is the problem maybe in the know limitation that when the pin is not known at compile time?

    Development

  • 💬 Battery Powered Sensors
    T tssk

    @Gilles-BILLARD Damn! Why did I order UNO if I could use another Pro Mini for programming... :)

    Announcements battery

  • How to manage dynamic number of sensors?
    T tssk

    In case someone is interested in the code for mysensors mqtt gateway using the DS2482.h library from https://github.com/paeaetech/paeae. The temperature conversion code is from example. I am omitting the mysensors setup.

    ...
    
    #include <DS2482.h>
    #include <Ethernet.h>
    #include <MySensors.h>
    #include <Wire.h>
    
    
    DS2482 ds( 0 );  //channels ds2482-800 is 0 to 7, DS2482-100 is just set 0
    byte dsData[8]; //holding for onewire capture
    byte dsAddr[8]; //1wire wire address and CRC
    
    MyMessage msgAddr( 0, V_ID );
    MyMessage msgTemp( 0, V_TEMP );
    
    
    void setup() {
    
      //Uses Wire library to communicate with DS2482 so be sure to call Wire.begin() before using the library.
      Wire.begin();
      ds.reset();
    
    }
    
    void presentation() {
    
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo( SKETCH_NAME, SKETCH_MAJOR_VER "." SKETCH_MINOR_VER );
    
    }
    
    void loop() {
    
      #ifdef MY_DEBUG
        Serial.println( "DBG: loop start" );
      #endif
    
      ds.wireResetSearch();
      ds.wireReset();
      ds.wireSkip();
      //need to send high power to bus??  Adding 5 volts to devices makes it work.
      ds.wireWriteByte( 0x44 ); //convert temperature on all devices
      delay( 1000 );
    
      byte sensorId = 0;
      while( ds.wireSearch( dsAddr ) ) {
    
        #ifdef MY_DEBUG
          Serial.print( sensorId );
          Serial.print( " : " );
        #endif
    
        char sensorAddr[17]; //eg. 280838211713012D
    
        for( int i = 0; i < 8; i++ ) {
          
          sensorAddr[i*2] = ( dsAddr[i] >> 4 ) + 0x30;
          if ( sensorAddr[i*2] > 0x39 ) {
            sensorAddr[i*2] += 7;
          }
          
          sensorAddr[i*2+1] = ( dsAddr[i] & 0x0f ) + 0x30;
          if ( sensorAddr[i*2+1] > 0x39 ) {
            sensorAddr[i*2+1] += 7;
          }
    
        }
    
        sensorAddr[16]  = '\0'; //always zero terminate string
        
        #ifdef MY_DEBUG
          Serial.print( sensorAddr );
          Serial.print( "\n" );
        #endif
    
        send( msgAddr.setSensor( sensorId ).set( sensorAddr ) );
    
        #ifdef MY_DEBUG
          Serial.print( sensorId );
          Serial.print( " : " );
        #endif
    
        if ( ds.crc8( dsAddr, 7 ) != dsAddr[7] ) {
          Serial.print( "CRC is not valid!" );
          return;
        }
    
        /*
        //test if device code DS18B20
        if ( dsAddr[0]==0x28 ) {
    
        //test if device code MAX31850
        if ( dsAddr[0]==0x3B ) {
        */
    
        //read temperature data.
        ds.wireReset(); //ds.reset();
        ds.selectChannel( 0 ); //necessary on -800
        ds.wireSelect( dsAddr );
        ds.wireWriteByte( 0xbe ); // Read Scratchpad command
    
        //display hex values of scratchpad
        for ( int i = 0; i < 9; i++ ) { // we need 9 bytes
          dsData[i] = ds.wireReadByte();
    
          #ifdef MY_DEBUG
            if ( dsData[i] < 16 ) {
              Serial.print( "0" );
            }
            Serial.print( dsData[i], HEX );
          #endif
        }
        
        //convert to decimal temperature
        int LowByte = dsData[0];
        int HighByte = dsData[1];
        int TReading = ( HighByte << 8 ) + LowByte;
        int SignBit = TReading & 0x8000; // test most sig bit
        if ( SignBit ) // negative
        {
                TReading = ( TReading ^ 0xffff ) + 1; // 2's comp
        }
    
        float Tc_100 = (double) TReading * 0.0625;
    
        if ( SignBit ) { // If its negative
                Tc_100 = 0 - Tc_100;
        }
    
        //print temp for each device
        #ifdef MY_DEBUG
          Serial.print( " : " );
          Serial.println( Tc_100 );
        #endif
    
        send ( msgTemp.setSensor( sensorId ).set( Tc_100, 2 ) );
    
        sensorId++;
      }
    
      #ifdef MY_DEBUG
        Serial.println( "DBG: loop end" );
      #endif
    
      delay( 60000 );
    }
    

    I am of course happy for any feedback. Especially if I am doing anything stupid as I am no programmer :)

    Development

  • How to manage dynamic number of sensors?
    T tssk

    @zboblamont Thanks for the tip. I am trying to avoid hardcoding any addresses - maybe I find out that it will be necessary at some point. But so far it looks fine:

    23:08:43.873 -> 0 MCO:BGN:INIT GW,CP=R-NGA---,FQ=8,REL=255,VER=2.3.2
    23:08:44.438 -> 585 GWT:TPC:IP=192.168.1.113
    23:08:45.468 -> 1589 MCO:BGN:STP
    23:08:45.468 -> 1591 MCO:REG:NOT NEEDED
    23:08:45.468 -> 1595 MCO:BGN:INIT OK,TSP=NA
    23:08:45.468 -> 1597 GWT:TPC:IP=192.168.1.113
    23:08:46.464 -> 2600 GWT:RMQ:CONNECTING...
    23:08:46.464 -> 2611 GWT:RMQ:OK
    23:08:46.464 -> 2613 GWT:TPS:TOPIC=1wire-out/0/255/0/0/17,MSG SENT
    23:08:46.497 -> 2619 GWT:TPS:TOPIC=1wire-out/0/255/3/0/11,MSG SENT
    23:08:46.497 -> 2625 GWT:TPS:TOPIC=1wire-out/0/255/3/0/12,MSG SENT
    23:08:46.497 -> DBG: loop start
    23:08:47.559 -> 0 : 280838211713012D
    23:08:47.559 -> 3704 GWT:TPS:TOPIC=1wire-out/0/0/1/0/42,MSG SENT
    23:08:47.592 -> 0 : 5A014B467FFF0C1044 : 21.62
    23:08:47.626 -> 3753 GWT:TPS:TOPIC=1wire-out/0/0/1/0/0,MSG SENT
    23:08:47.692 -> 1 : 28A82B7D17130189
    23:08:47.692 -> 3825 GWT:TPS:TOPIC=1wire-out/0/1/1/0/42,MSG SENT
    23:08:47.692 -> 1 : 53014B467FFF0C102D : 21.19
    23:08:47.758 -> 3876 GWT:TPS:TOPIC=1wire-out/0/1/1/0/0,MSG SENT
    23:08:47.824 -> 2 : 28949D2816130138
    23:08:47.824 -> 3948 GWT:TPS:TOPIC=1wire-out/0/2/1/0/42,MSG SENT
    23:08:47.824 -> 2 : 5F014B467FFF0C1012 : 21.94
    23:08:47.858 -> 3999 GWT:TPS:TOPIC=1wire-out/0/2/1/0/0,MSG SENT
    23:08:47.924 -> 3 : 282C3C2A16130167
    23:08:47.924 -> 4071 GWT:TPS:TOPIC=1wire-out/0/3/1/0/42,MSG SENT
    23:08:47.957 -> 3 : 56014B467FFF0C107B : 21.37
    23:08:47.990 -> 4122 GWT:TPS:TOPIC=1wire-out/0/3/1/0/0,MSG SENT
    23:08:48.057 -> 4 : 28FC801F16130104
    23:08:48.057 -> 4194 GWT:TPS:TOPIC=1wire-out/0/4/1/0/42,MSG SENT
    23:08:48.057 -> 4 : 5C014B467FFF0C10D7 : 21.75
    23:08:48.123 -> 4245 GWT:TPS:TOPIC=1wire-out/0/4/1/0/0,MSG SENT
    23:08:48.190 -> 5 : 2832312A161301C3
    23:08:48.190 -> 4317 GWT:TPS:TOPIC=1wire-out/0/5/1/0/42,MSG SENT
    23:08:48.190 -> 5 : 58014B467FFF0C10C2 : 21.50
    23:08:48.223 -> 4368 GWT:TPS:TOPIC=1wire-out/0/5/1/0/0,MSG SENT
    23:08:48.322 -> 6 : 28CAD31F16130180
    23:08:48.322 -> 4440 GWT:TPS:TOPIC=1wire-out/0/6/1/0/42,MSG SENT
    23:08:48.322 -> 6 : 57014B467FFF0C1038 : 21.44
    23:08:48.356 -> 4489 GWT:TPS:TOPIC=1wire-out/0/6/1/0/0,MSG SENT
    23:08:48.422 -> 7 : 28FFE4493118014F
    23:08:48.422 -> 4560 GWT:TPS:TOPIC=1wire-out/0/7/1/0/42,MSG SENT
    23:08:48.422 -> 7 : 58014B467FFF0C10C2 : 21.50
    23:08:48.488 -> 4612 GWT:TPS:TOPIC=1wire-out/0/7/1/0/0,MSG SENT
    23:08:48.555 -> 8 : 28FF345E311801AF
    23:08:48.555 -> 4683 GWT:TPS:TOPIC=1wire-out/0/8/1/0/42,MSG SENT
    23:08:48.555 -> 8 : 5B014B467FFF0C1007 : 21.69
    23:08:48.621 -> 4734 GWT:TPS:TOPIC=1wire-out/0/8/1/0/0,MSG SENT
    23:08:48.687 -> 9 : 28FF094131180165
    23:08:48.687 -> 4806 GWT:TPS:TOPIC=1wire-out/0/9/1/0/42,MSG SENT
    23:08:48.687 -> 9 : 55014B467FFF0C10BE : 21.31
    23:08:48.721 -> 4855 GWT:TPS:TOPIC=1wire-out/0/9/1/0/0,MSG SENT
    23:08:48.787 -> 10 : 28FFE513311802A3
    23:08:48.787 -> 4927 GWT:TPS:TOPIC=1wire-out/0/10/1/0/42,MSG SENT
    23:08:48.820 -> 10 : 51014B467FFF0C10AB : 21.06
    23:08:48.853 -> 4980 GWT:TPS:TOPIC=1wire-out/0/10/1/0/0,MSG SENT
    23:08:48.920 -> 11 : 28FF2B1F31180231
    23:08:48.920 -> 5052 GWT:TPS:TOPIC=1wire-out/0/11/1/0/42,MSG SENT
    23:08:48.920 -> 11 : 56014B467FFF0C107B : 21.37
    23:08:48.986 -> 5103 GWT:TPS:TOPIC=1wire-out/0/11/1/0/0,MSG SENT
    23:08:48.986 -> DBG: loop end
    
    Development

  • How to manage dynamic number of sensors?
    T tssk

    @mfalkvidd I did not see it - thanks for mentioning it.

    I think this is what I was looking for - the sketch uses one MyMessage msg(0,V_TEMP); for values from all DS18B20 with such code construction

      // Read temperatures and send them to controller 
      for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {
          ...
          // Send in the new temperature
          send(msg.setSensor(i).set(temperature,1));
          ...
      }
    

    I thought I will need to set up MyMessage msg(0,V_TEMP) x number_of_sensors which would be terrible.

    I guess if I extend the code with MyMessage msg(0,V_ID) to send also the 1wire address it will be what I am looking for.

    Thanks!

    Development

  • How to manage dynamic number of sensors?
    T tssk

    Hello

    I build mqtt mysensors gateway with DS2482-100 to handle many (currently 15 DS18B20) 1wire sensors.

    My idea was that the gateway will dynamically start to report each attached 1wire sensors 1wire address and value automatically without necessity to change the sketch before attaching new sensor. But from what I see I need to set MyMessage(uint8_t childSensorId, uint8_t variableType); first.

    Is there some best practice pattern how to do it?

    Thanks

    Tomas

    Development

  • 💬 Battery Powered Sensors
    T tssk

    So I ordered Arduino Uno for programming my Pro Minis. And going to experiment with 2xAA or 3xAA setup without step up booster (they are whining anyway so I will be happy if I get rid of it :)

    Thank everyone for help!

    Announcements battery

  • 💬 Battery Powered Sensors
    T tssk

    @skywatch said in 💬 Battery Powered Sensors:

    I think you will find that all the 'good stuff' from the low power library is included in mysensors sleep function anyway.

    So when I use sleep() mysensors library overloads the generic arduino sleep?

    I suggest using minicore (it is easy to install and all works from within the arduino IDE you are used to) and set internal oscillator and disable BoD. You will need a programmer (a few dollars) or you can use another arduino as programmer. but that is more time consuming to set up and easier to mess up as well!

    I look at the git repo and I more confused now. I thought it is some kind of bootloader/firmware I flash. What is Arduino core? I never heard that term.

    Good that you got rid of the booster!

    I wonder why the booster is recommended here https://www.mysensors.org/build/battery ? Or did I misinterpreted?

    Announcements battery

  • 💬 Battery Powered Sensors
    T tssk

    @tssk said in 💬 Battery Powered Sensors:

    I removed the step up booster connected + directly to VCC but the node stopped working - only the arduino onboard led is constantly on.

    The problem was that the batteries I used were not completely fresh. I googled that Arduino pro mini need at least 2.7V to operate. Using fresh batteries the node is working. And it shows 6.0mA in sleep and 25.4mA when transmitting.

    So using the stepup booster adds 6.5mA in sleep and 65mA when transmitting to consumption?

    I also found LowPower library (https://github.com/rocketscream/Low-Power) but it seems to interfere with mysensors library (https://github.com/rocketscream/Low-Power/issues/80). Any experience?

    Announcements battery

  • 💬 Battery Powered Sensors
    T tssk

    I removed the step up booster connected + directly to VCC but the node stopped working - only the arduino onboard led is constantly on.

    I also tried to measure the step up booster alone and it is showing 0.05 at 20mA on multimeter settings.

    I am now really confused and I am not sure what to conclude from that...

    Announcements battery

  • 💬 Battery Powered Sensors
    T tssk

    I hope I am measuring it correctly.

    It shows 12.5 when in sleep and up to 90 when transmitting/measuring.

    Any one can interpret that for me please? :)

    IMG_20210225_151612.jpeg

    Announcements battery

  • 💬 Battery Powered Sensors
    T tssk

    @TheoL I see so you measure every tim e but send only sometimes. Nice idea thanks.

    Announcements battery

  • 💬 Battery Powered Sensors
    T tssk

    IMG_20210225_121037.jpeg

    IMG_20210225_121053.jpeg

    Announcements battery

  • 💬 Battery Powered Sensors
    T tssk

    @skywatch

    • This is room sensor and I would like to react to changes in temperature and airquality - I was thinking that I could prolong the interval up to 12min. What do you think is optimal measurements rate for room thermostat?

    • Is it possible / necessary to put the radio module to sleep? How to do that?

    • So far I did not mess with the Arduino bootloader but I would like to :) Any link that I could read about it? And specifically about the minicore you mention?

    • I do not understand what you mean by the pull-up resistors?

    • I have my node in the middle of the room around 20-24C that sould not be the problem. Actually it is it main purpose to provide data for optimal room temperature.

    • I included step up boosted based on recommendation on the https://www.mysensors.org/build/battery page. I thought it should use the batteries most efficiently. I think I could go with 3 AA batteries. Will I need to regulate the voltage or can I power the radio and bme modules directly?

    Announcements battery

  • 💬 Battery Powered Sensors
    T tssk

    @mfalkvidd

    • I did not know that I need to turn BME off ů how to do that?

    • Only thing I found is that Arduino has deepSleep() - but I am not sure if I can use it.

    • I am using the default Bw125Cr45Sf128 but thinking about testing Bw125Cr48Sf4096 to achieve greater range.

    • Booster is the whining one - https://www.laskarduino.cz/step-up-boost-menic-s-me2108-33v-480ma/

    • Is there a way I can measure power draw with multimeter?

    // Enable debug prints
    //#define MY_DEBUG
    
    // Enable passive mode
    #define MY_PASSIVE_NODE
    
    // Passive mode requires static node ID
    #define MY_NODE_ID 100
    
    // Enable and select radio type attached
    //#define MY_RADIO_RF24
    //#define MY_RADIO_NRF5_ESB
    //#define MY_RADIO_RFM69
    #define MY_RADIO_RFM95
    
    //#define MY_DEBUG_VERBOSE_RFM95
    #define MY_RFM95_FREQUENCY (RFM95_868MHZ)
    //#define MY_RFM95_MODEM_CONFIGRUATION RFM95_BW31_25CR48SF512
    #define MY_RFM95_CS_PIN 8
    #define MY_RFM95_IRQ_PIN 2
    
    #include <MySensors.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <Adafruit_Sensor.h>
    #include "Adafruit_BME680.h"
    
    #define BME_SCK 13
    #define BME_MISO 12
    #define BME_MOSI 11
    #define BME_CS 10
    
    //#define SEALEVELPRESSURE_HPA (1013.25)
    
    // Initialize general message
    MyMessage msgTemp( 1, V_TEMP );
    MyMessage msgHumi( 2, V_HUM );
    MyMessage msgAirq( 3, V_LEVEL );
    
    //Adafruit_BME680 bme; // I2C
    Adafruit_BME680 bme(BME_CS); // hardware SPI
    //Adafruit_BME680 bme(BME_CS, BME_MOSI, BME_MISO,  BME_SCK);
    
    void setup()
    {
      analogReference(INTERNAL);
    
      if (!bme.begin()) {
        Serial.println( "ERR: BME680 not found" );
        while (1);
      }
      // Set up oversampling and filter initialization
      bme.setTemperatureOversampling(BME680_OS_8X);
      //bme.setPressureOversampling(BME680_OS_4X);
      bme.setHumidityOversampling(BME680_OS_2X);
      bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
      bme.setGasHeater(320, 150); // 320*C for 150 ms
    
      delay(2000);
      
    }
    
    void presentation()
    {
    	// Send the sketch version information to the gateway and controller
    	sendSketchInfo("Room sensor", "4.0");
    
    	// Register all sensors to gw (they will be created as child devices)
      wait(100);
    	present( 1, S_TEMP );
      wait(100);
      present( 2, S_HUM );
      wait(100);
      present( 3, S_AIR_QUALITY );
    
    }
    
    void loop()
    {
    
      int batt = analogRead( A3 );
      // 1M, 470K divider across battery and using internal ADC ref of 1.1V
      // Sense point is bypassed with 0.1 uF cap to reduce noise at that point
      // ((1e6+470e3)/470e3)*1.1 = Vmax = 3.44 Volts
      // 3.44/1023 = Volts per bit = 0.003363075
      int battP = batt / 10;
      #ifdef MY_DEBUG
          float battV  = batt * 0.003363075;
          Serial.print( "Battery Voltage: " );
          Serial.print( battV );
          Serial.println(" V");
          Serial.print( "Battery percent: " );
          Serial.print( battP );
          Serial.println(" %");
      #endif
      wait(100);
      sendBatteryLevel( battP );
      
    
      if (! bme.performReading()) {
        Serial.println( "ERR: BME680 reading failed" );
        return;
      }
      
      float temp = bme.temperature;
      #ifdef MY_DEBUG
        Serial.print( "DBG: Temperature = " );
        Serial.print( temp );
        Serial.println( " C" );
      #endif
      wait(100);
      send(msgTemp.set( temp, 2 ));
      
      /*
      float pres = bme.pressure/100.00;
      #ifdef MY_DEBUG
        Serial.print( "DBG: Pressure = " );
        Serial.print( pres );
        Serial.println( " hPa" );
      #endif
      wait(100);
      send(msgPres.set(pres,2));
      */
      
      float humi = bme.humidity;
      #ifdef MY_DEBUG
        Serial.print( "DBG: Humidity = " );
        Serial.print( humi );
        Serial.println( " %" );
      #endif
      wait(100);
      send(msgHumi.set( humi, 2 ));
      
      /*
      float alti = bme.readAltitude(SEALEVELPRESSURE_HPA);
      #ifdef MY_DEBUG
        Serial.print( "DBG: Approx. Altitude = " );
        Serial.print( alti );
        Serial.println( " m" );
      #endif
      wait(100);
      send(msgPosi.set(alti,2));
      */
    
      float airq = bme.gas_resistance / 1000.0;
      #ifdef MY_DEBUG
        Serial.print("DBG: Gas Resistance = ");
        Serial.print( gas );
        Serial.println(" KOhms");
      #endif
      wait(100);
      send(msgAirq.set( airq, 2 ));
      
      
      sleep(10000);
    	//sleep(180000);
    }
    
    Announcements battery

  • 💬 Battery Powered Sensors
    T tssk

    Hello

    I would like to ask for help with passive battery powered node I created with following components:

    • Arduino pro mini 8MHz - voltage regulator and power LED removed
    • SX1276 based 868MHz LoRa radio
    • BME680 sensor
    • DC-DC 3.3V step-up booster

    I created a battery measuring circuit according to scheme on this page ( https://www.mysensors.org/build/battery ).

    The problem is the two fresh new AA batteries lasted less than 14 days and stopped when the circuit measured 36%.

    2x1.5V AA Aerocell following start and end values:

    09.02.2021 16:45 102% (start) : 1.610V and 1.610V
    22.02.2021 04:15 36% (end) : 1.001V and -0.150V

    2021-02-25_07-36.png

    The node code is sleeping for 6 minutes between each sensing and sending data.

    sleep(180000);
    

    14 days seems very short to me. Is that normal? Is there something I can to make it last longer?

    Thanks

    Announcements battery

  • 💬 Battery Powered Sensors
    T tssk

    @mfalkvidd Thanks.

    Announcements battery

  • 💬 Battery Powered Sensors
    T tssk

    @mfalkvidd You are right :) I did not know that.

    SPI: 10 (SS), 11 (MOSI), 12 (MISO), 13 (SCK). These pins support SPI communication, which, although provided by the underlying hardware, is not currently included in the Arduino language.
    LED: 13. There is a built-in LED connected to digital pin 13. When the pin is HIGH value, the LED is on, when the pin is LOW, it's off.

    https://www.arduino.cc/en/pmwiki.php?n=Main/ArduinoBoardProMini

    Should I remove the LED to save power? Or it is marginal?

    Announcements battery

  • 💬 Battery Powered Sensors
    T tssk

    So I used hot glue and it is better. Now I can hear the squeal only when I put my ear directly to the PCB. Thanks for the tips.

    @TheoL I have no idea how to measure that.

    I noticed that when the radio is transmitting the LED on the Arduino Pro Mini (not the power one) starts blinking very tiny. I still plan to remove the power LED and voltage regulator from the Arduino.

    Announcements battery

  • 💬 Battery Powered Sensors
    T tssk

    @zboblamont It is not electrical noise but audio noise I can hear. Sorry if I use improper terms.

    Announcements battery
  • Login

  • Don't have an account? Register

  • Login or register to search.
  • First post
    Last post
0
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular