Two advice please - *.ino development

Moderators: grovkillen, Stuntteam, TD-er

Post Reply
Message
Author
mackowiakp
Normal user
Posts: 527
Joined: 07 Jun 2018, 06:47
Location: Gdynia/Poland

Two advice please - *.ino development

#1 Post by mackowiakp » 31 Oct 2019, 20:45

Below is the code for the FM tuner on which I started working. It works, but I don't really know why :lol:
I have two questions.
The variable PCONFIG(0) contains the tuner I2C address. But the PLUGIN_INIT section not use any address. Oddly enough, the whole thing works on the default address, regardless of what address I set in the GUI.
How correctly should I use the PCONFIG(0) variable to make the tuner initialize correctly? I looked at other plugins but found no answer.
The second question is how to write the value to a variable stored in flash.
The "volfm" variable is defined in the PLUGIN_WRITE section. In this variable the volume value is stored. I want to save it to flash so that after powercycle or reboot, the volume remains unchanged.
That's why I used the line:

Code: Select all

PCONFIG(1) = volfm;
But unfortunately after reboot the volume remains the same as it was previously set in the GUI.
So how do you save PCONFIG(1) to flash correctly?

Will be glad for kind answer.

Code: Select all

#ifdef USES_P089

#define PLUGIN_089
#define PLUGIN_ID_089         89
#define PLUGIN_NAME_089       "Radio FM - RDA5807M [TESTING]"
#define PLUGIN_VALUENAME1_089 ""

#include <Wire.h>
#include <radio.h>
#include <RDA5807M.h>

RDA5807M radio;

boolean Plugin_089(byte function, struct EventStruct *event, String& string)
{
  boolean success = false;
int minFreq = 875;
int maxFreq = 1080;

  switch (function)
  {

    case PLUGIN_DEVICE_ADD:
      {
        Device[++deviceCount].Number = PLUGIN_ID_089;
        Device[deviceCount].Type = DEVICE_TYPE_I2C;
        Device[deviceCount].VType = SENSOR_TYPE_NONE;
        Device[deviceCount].Ports = 0;
        Device[deviceCount].PullUpOption = false;
        Device[deviceCount].InverseLogicOption = false;
        Device[deviceCount].FormulaOption = false;
        Device[deviceCount].ValueCount = 0;
        Device[deviceCount].SendDataOption = false;
        Device[deviceCount].TimerOption = false;
        Device[deviceCount].GlobalSyncOption = false;
        break;
      }

    case PLUGIN_GET_DEVICENAME:
      {
        string = F(PLUGIN_NAME_089);
        break;
      }

    case PLUGIN_WEBFORM_LOAD:
      {
        byte choice = PCONFIG(0);
        int optionValues[5] = { 0x10, 0x11, 0x20, 0x21, 0x60 };
        addFormSelectorI2C(F("p089_adr"), 5, optionValues, choice);
        addFormCheckBox(F("Enable default volume"), F("p089_vol"), PCONFIG(5));
        addFormNote(F("Uncheck to use the last volume set"));
        addFormNumericBox(F("Default volume"), F("volume"), PCONFIG(1), 0, 15);
        addFormCheckBox(F("Mono"), F("p089_mono"), PCONFIG(2));
        addFormCheckBox(F("Bass Boost"), F("p089_bass"), PCONFIG(3));
        addFormSubHeader(F("Stations tuning"));
        addFormNote(F("Frequencies should be entered without a comma or period, e.g. 1050 means 105.0 MHz in range 875 to 1080"));

        addFormCheckBox(F("Enable default station"), F("p089_station"), PCONFIG(6));
        addFormNote(F("Uncheck to use last station tuned"));
        addFormNumericBox(F("Default station"), F("station"), PCONFIG(4), minFreq, maxFreq);
        addUnit(F("MHz * 10"));
          success = true;
          break;
      }

    case PLUGIN_WEBFORM_SAVE:
      {
        PCONFIG(0) = getFormItemInt(F("p089_adr"));
        PCONFIG(1) = getFormItemInt(F("volume"));
        PCONFIG(2) = isFormItemChecked(F("p089_mono"));
        PCONFIG(3) = isFormItemChecked(F("p089_bass"));
        PCONFIG(4) = getFormItemInt(F("station"));
        PCONFIG(5) = isFormItemChecked(F("p089_vol"));
        PCONFIG(6) = isFormItemChecked(F("p089_station"));

        success = true;
        break;
      }

    case PLUGIN_INIT:
      {
        radio.init();
        radio.setBand(RADIO_BAND_FM);
        radio.setFrequency(PCONFIG(4)*10);
        radio.setBassBoost(true);
        radio.setVolume(PCONFIG(1));
        radio.setMono(true);
        radio.setMute(false);

        success = true;
        break;
      }
      
    case PLUGIN_WRITE:
      {
        String command = parseString(string, 1);
        String param = parseString(string, 2);

        if (command == F("tune"))
        {
          int freq;
          if (validIntFromString(param, freq)) {
           if (freq >= minFreq && freq <= maxFreq)
           {
            radio.setFrequency(freq*10);
            if (loglevelActiveFor(LOG_LEVEL_INFO)) {
              String log = F("FM : Freq=");
              log += freq;
              addLog(LOG_LEVEL_INFO, log);
            }
           }
          }
          success = true;
        } 

        if (command == F("seekup"))
        {
          String log = F("FM : Seek Up");
          radio.seekUp();
          addLog(LOG_LEVEL_INFO, log);
          success = true;
        }

        if (command == F("seekdown"))
        {
          String log = F("FM : Seek Down");
          radio.seekUp();
          addLog(LOG_LEVEL_INFO, log);
          success = true;
        }
        if (command == F("volfm"))
        {
          int volfm;
          String log = F("FM : vol=");

          if (volfm < 1) volfm = 0;
          if (volfm > 15) volfm = 15;
          volfm = param.toInt();
          PCONFIG(1) = volfm;
          radio.setVolume(volfm);
          log += volfm;

          addLog(LOG_LEVEL_INFO, log);
          success = true;
        }
        break;
      } 
  }
  return success;
}
#endif // USES_P089

mackowiakp
Normal user
Posts: 527
Joined: 07 Jun 2018, 06:47
Location: Gdynia/Poland

Re: Two advice please - *.ino development

#2 Post by mackowiakp » 01 Nov 2019, 17:32

The first secret was explained. Just a chip has no possibility to change the I2C address. The chip has permanent addresses 0x10 and 0x11.
Hence, these addresses were explicitly entered in the RDA5807M.cpp file. The address selection menu is therefore unnecessary.

But I still don't know how to store PCONFIG(1) variable in flash in PLUGIN_WRITE section. As I wrote
The "volfm" variable is defined in the PLUGIN_WRITE section. In this variable the volume value is stored. I want to save it to flash so that after powercycle or reboot, the volume remains unchanged.
That's why I used the line:

Code: Select all

PCONFIG(1) = volfm;
But unfortunately after reboot the volume remains the same as it was previously set in the GUI.
So how do you save PCONFIG(1) to flash correctly?

Any idea?

TD-er
Core team member
Posts: 8643
Joined: 01 Sep 2017, 22:13
Location: the Netherlands
Contact:

Re: Two advice please - *.ino development

#3 Post by TD-er » 01 Nov 2019, 18:00

The PCONFIG(...) is a macro I added to make the code more readable.
It will be expanded to a much longer piece of code referring to the settings for plugin config values.

So you can use PCONFIG(...) to access these settings (read and write).

If you look at the code of other plugins, you see there is a case for PLUGIN_WEBFORM_LOAD and PLUGIN_WEBFORM_SAVE.
See for a rather clean example the code for GPS plugin: https://github.com/letscontrolit/ESPEas ... 82_GPS.ino

The LOAD case does read the settings and wrap them in the web interface page.
The SAVE case (you're looking for) does get the values back from the web interface page and stores the updated values in the settings.

Just make sure your code does set

Code: Select all

success = true;
If the success bool is not set to true, the handling of plugin code may not continue (and maybe not save the settings to flash)

mackowiakp
Normal user
Posts: 527
Joined: 07 Jun 2018, 06:47
Location: Gdynia/Poland

Re: Two advice please - *.ino development

#4 Post by mackowiakp » 01 Nov 2019, 18:58

As for the case PLUGIN_WEBFORM_LOAD and PLUGIN_WEBFORM_SAVE, they work with me correctly. I enter data from the GUI and write correctly.
Then I use the values PCONFIG(..) in the program code and everything is OK.
But I want to write to the PCONFIG(..) variable in the PLUGIN_WRITE section to save the current volume value in flash.
I wanted to use this piece of code for this:

Code: Select all

        if (command == F("volfm"))
        {
          int volfm;
          String log = F("FM : vol=");

          if (volfm < 1) volfm = 0;
          if (volfm > 15) volfm = 15;
          volfm = param.toInt();
          PCONFIG(1) = volfm;
          radio.setVolume(volfm);
          log += volfm;

          addLog(LOG_LEVEL_INFO, log);
          success = true;
        }
Unfortunately, it doesn't work, so what can I do?

TD-er
Core team member
Posts: 8643
Joined: 01 Sep 2017, 22:13
Location: the Netherlands
Contact:

Re: Two advice please - *.ino development

#5 Post by TD-er » 01 Nov 2019, 21:00

Code: Select all

          int volfm;
          String log = F("FM : vol=");

          if (volfm < 1) volfm = 0;
          if (volfm > 15) volfm = 15;
          volfm = param.toInt();
          PCONFIG(1) = volfm;
I think you should assign the `volfm` value first before comparing it :)

Code: Select all

int volfm = param.toInt();
Als make sure these are correct:

Code: Select all

String command = parseString(string, 1);
String param = parseString(string, 2);
To be sure these are what you think they are, you may want to log them strings and check.

mackowiakp
Normal user
Posts: 527
Joined: 07 Jun 2018, 06:47
Location: Gdynia/Poland

Re: Two advice please - *.ino development

#6 Post by mackowiakp » 02 Nov 2019, 11:06

OMG !!! You are right. So I changed this part of code to the one listed below.
But still can not write "volfm" value as PCONFIG(1) to flash. What to do?

Code: Select all

        if (command == F("volfm"))
        {
          int volfm;
          String log = F("FM : vol=");
          if (validIntFromString(param, volfm)) {
          if (volfm < 1) volfm = 0;
          if (volfm > 15) volfm = 15;
          PCONFIG(1) = volfm;
          radio.setVolume(volfm);
          log += volfm;
          addLog(LOG_LEVEL_INFO, log);
          }
          success = true;
        }

TD-er
Core team member
Posts: 8643
Joined: 01 Sep 2017, 22:13
Location: the Netherlands
Contact:

Re: Two advice please - *.ino development

#7 Post by TD-er » 02 Nov 2019, 17:08

You should give a bit more information, like the complete code and/or some log output and examples of commands you give.

mackowiakp
Normal user
Posts: 527
Joined: 07 Jun 2018, 06:47
Location: Gdynia/Poland

Re: Two advice please - *.ino development

#8 Post by mackowiakp » 02 Nov 2019, 17:16

Below full code I wrote so far.

Code: Select all

#ifdef USES_P089
//#######################################################################################################
//############################# Plugin 089: P089_RadioFM ############################################
//#######################################################################################################

// I2C-Address RDA Chip for sequential access 0x10 - unchagneable
// I2C-Address RDA Chip for Index access 0x11 - unchagneable

#define PLUGIN_089
#define PLUGIN_ID_089         89
#define PLUGIN_NAME_089       "Radio FM - RDA5807M [TESTING]"
#define PLUGIN_VALUENAME1_089 "Frequency"
#define PLUGIN_VALUENAME2_089 "Volume"

#include <Wire.h>
#include <radio.h>
#include <RDA5807M.h>

RDA5807M radio;

boolean Plugin_089(byte function, struct EventStruct *event, String& string)
{
  boolean success = false;
  int minFreq = 875;
  int maxFreq = 1080;
  int freq;

  switch (function)
  {

    case PLUGIN_DEVICE_ADD:
      {
        Device[++deviceCount].Number = PLUGIN_ID_089;
        Device[deviceCount].Type = DEVICE_TYPE_I2C;
        Device[deviceCount].VType = SENSOR_TYPE_DUAL;
        Device[deviceCount].Ports = 0;
        Device[deviceCount].PullUpOption = false;
        Device[deviceCount].InverseLogicOption = false;
        Device[deviceCount].FormulaOption = false;
        Device[deviceCount].DecimalsOnly = true;
        Device[deviceCount].ValueCount = 2;
        Device[deviceCount].SendDataOption = true;
        Device[deviceCount].TimerOption = true;
        Device[deviceCount].GlobalSyncOption = true;
        break;
      }

    case PLUGIN_GET_DEVICENAME:
      {
        string = F(PLUGIN_NAME_089);
        break;
      }

    case PLUGIN_GET_DEVICEVALUENAMES:
    {   
        strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_089));
        strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_089));
        break;
    }

    case PLUGIN_WEBFORM_LOAD:
      {

        addFormNote(F("I2C-Address of RDA5807M Chip is 0x10, impossible to change"));
        addFormCheckBox(F("Mute after boot"), F("p089_mute"), PCONFIG(0));
        addFormCheckBox(F("Enable default volume"), F("p089_vol"), PCONFIG(5));
        addFormNote(F("Uncheck to use the last volume set"));
        addFormNumericBox(F("Default volume"), F("volume"), PCONFIG(1), 0, 15);
        addFormCheckBox(F("Mono"), F("p089_mono"), PCONFIG(2));
        addFormCheckBox(F("Bass Boost"), F("p089_bass"), PCONFIG(3));
        addFormSubHeader(F("Stations tuning"));
        addFormNote(F("Frequency should be entered without a comma or period in range 875 to 1080, e.g. 1050 means 105.0 MHz"));

        addFormCheckBox(F("Enable default station"), F("p089_station"), PCONFIG(6));
        addFormNote(F("Uncheck to use last station tuned"));
        addFormNumericBox(F("Default station"), F("station"), PCONFIG(4), minFreq, maxFreq);
        addUnit(F("MHz * 10"));
          success = true;
          break;
      }

    case PLUGIN_WEBFORM_SAVE:
      {
        PCONFIG(0) = isFormItemChecked(F("p089_mute"));
        PCONFIG(1) = getFormItemInt(F("volume"));
        PCONFIG(2) = isFormItemChecked(F("p089_mono"));
        PCONFIG(3) = isFormItemChecked(F("p089_bass"));
        PCONFIG(4) = getFormItemInt(F("station"));
        PCONFIG(5) = isFormItemChecked(F("p089_vol"));
        PCONFIG(6) = isFormItemChecked(F("p089_station"));

        success = true;
        break;
      }

    case PLUGIN_INIT:
      {
        delay(1000); // Dont know why.... does not work without after powercycle
        radio.init();
        radio.setBand(RADIO_BAND_FM);
        radio.setFrequency(PCONFIG(4) * 10);
        radio.setBassBoost(PCONFIG(3));
        radio.setVolume(PCONFIG(1));
        radio.setMono(PCONFIG(2));
        radio.setMute(PCONFIG(0));

        success = true;
        break;
      }

/*   case PLUGIN_READ:
      {
          success = true;
        }
        break; 
      } */

    case PLUGIN_WRITE:
      {
        String command = parseString(string, 1);
        String param = parseString(string, 2);

        if (command == F("tune"))
        {
          if (validIntFromString(param, freq)) {
           if (freq >= minFreq && freq <= maxFreq)
           {
            radio.setFrequency(freq*10);
//          PCONFIG(4) = freq;
            if (loglevelActiveFor(LOG_LEVEL_INFO))
            {
              String log = F("FM : Freq=");
              log += freq;
              addLog(LOG_LEVEL_INFO, log);
            }
           }
          }
          success = true;
        } 

        if (command == F("mutefm"))
        {
          int mutefm;
          String log = F("FM : Mute=");
          mutefm = param.toInt();
          if (mutefm == 0 || mutefm == 1)
           {
            if (mutefm == 1) radio.setMute(true);
            if (mutefm == 0) radio.setMute(false);
            log += mutefm;
            addLog(LOG_LEVEL_INFO, log);
           }
          success = true;
        }

        if (command == F("volfm"))
        {
          int volfm;
          String log = F("FM : vol=");
          if (validIntFromString(param, volfm))
          {
           if (volfm < 1) volfm = 0;
           if (volfm > 15) volfm = 15;
           PCONFIG(1) = volfm;
           radio.setVolume(volfm);
           log += volfm;
           addLog(LOG_LEVEL_INFO, log);
          }
          success = true;
        }

        if (command == F("volfmup"))
        {
          int volfm;
          String log = F("FM : vol=");
          volfm = radio.getVolume();
          volfm++;
          if (volfm > 15) volfm = 15;
          radio.setVolume(volfm);
          PCONFIG(1) = volfm;
          log += volfm;
          addLog(LOG_LEVEL_INFO, log);
          success = true;
        }

        if (command == F("volfmdown"))
        {
          int volfm;
          String log = F("FM : vol=");
          volfm = radio.getVolume();
          volfm--;
          if (volfm < 1) volfm = 0;
          radio.setVolume(volfm);
          PCONFIG(1) = volfm;
          log += volfm;
          addLog(LOG_LEVEL_INFO, log);
          success = true;
        }
        break;
      } 
  }
  return success;
}

#endif // USES_P089

TD-er
Core team member
Posts: 8643
Joined: 01 Sep 2017, 22:13
Location: the Netherlands
Contact:

Re: Two advice please - *.ino development

#9 Post by TD-er » 02 Nov 2019, 19:07

And what is the exact command you gave?

TD-er
Core team member
Posts: 8643
Joined: 01 Sep 2017, 22:13
Location: the Netherlands
Contact:

Re: Two advice please - *.ino development

#10 Post by TD-er » 02 Nov 2019, 19:25

Also I don't know in what unit you have to give the frequency.
You don't have supplied a link to the RDA5807M library
What's strange is that your comment (addUnit) does state the unit is in "MHz x 10", which does sound like "x100kHz" Is that correct?
But the entered value is multiplied by 10 when sending it to the library. (I would expect you had to divide it by 10)
What type of parameter does the set frequency function need? Unsigned int? float?

I would assume a float and thus you need to cast the value to a float.
For example:

Code: Select all

radio.setFrequency(static_cast<float>(PCONFIG(4)) / 10.0);

mackowiakp
Normal user
Posts: 527
Joined: 07 Jun 2018, 06:47
Location: Gdynia/Poland

Re: Two advice please - *.ino development

#11 Post by mackowiakp » 02 Nov 2019, 19:30

For example:

Code: Select all

volfm,10
I learn all the syntax`s needed one by one, because I'm going to publish the code as "Develop" on Github.
And I still don't know how to write parameters to flash in other sections than SAVE.

mackowiakp
Normal user
Posts: 527
Joined: 07 Jun 2018, 06:47
Location: Gdynia/Poland

Re: Two advice please - *.ino development

#12 Post by mackowiakp » 02 Nov 2019, 19:49

Also I don't know in what unit you have to give the frequency.
Frequency must be given in the form for example for frequency 105,7 MHz must be 10570
You don't have supplied a link to the RDA5807M library
https://github.com/mathertel/Radio/blob ... A5807M.cpp
What's strange is that your comment (addUnit) does state the unit is in "MHz x 10", which does sound like "x100kHz" Is that correct?
Its only comment, could be changed in any form You suggest as more "human readable".
But the entered value is multiplied by 10 when sending it to the library. (I would expect you had to divide it by 10)
As European standards stands, FM frequency resolution is one decimal point.
So for example my favorite station use 99,9MHz, must be written in command or setup window in form 999 (as default).
But during call library needs has a form 9990.
What type of parameter does the set frequency function need? Unsigned int? float?
unsigned int, but I use int because strange warning during compilation from RDA5807M library.

TD-er
Core team member
Posts: 8643
Joined: 01 Sep 2017, 22:13
Location: the Netherlands
Contact:

Re: Two advice please - *.ino development

#13 Post by TD-er » 02 Nov 2019, 20:22

mackowiakp wrote: 02 Nov 2019, 19:30 For example:

Code: Select all

volfm,10
I learn all the syntax`s needed one by one, because I'm going to publish the code as "Develop" on Github.
And I still don't know how to write parameters to flash in other sections than SAVE.
As far as I can see, you do write stuff to flash when pressing the submit button on the webpage.
If you also need to save it after setting the values using a command, you should call the save command also.
I would not advice to call the save from the plugin itself, since you will have a lot of writes during the day.
So better call save as a command when you really need it (e.g. after changing a channel) and not when you just change the volume for example.

mackowiakp
Normal user
Posts: 527
Joined: 07 Jun 2018, 06:47
Location: Gdynia/Poland

Re: Two advice please - *.ino development

#14 Post by mackowiakp » 02 Nov 2019, 20:43

OK, so You have "tune" command:

Code: Select all

        if (command == F("tune"))
        {
          if (validIntFromString(param, freq)) {
           if (freq >= minFreq && freq <= maxFreq)
           {
            radio.setFrequency(freq*10);
//          PCONFIG(4) = freq;
            if (loglevelActiveFor(LOG_LEVEL_INFO))
            {
              String log = F("FM : Freq=");
              log += freq;
              addLog(LOG_LEVEL_INFO, log);
            }
           }
          }
          success = true;
        } 
PCONFIG is commented at this time, but still how can I save "freq" to PCONFIG(4) to flash?

Another problem is RDS. I can place RDS info string to log and it works for me. But it is not possible - as far as I know - to store it in any variable/structure or so.
It is important because different displays can be use. So how to "leave" it for use by another driver that is for any display driver?

TD-er
Core team member
Posts: 8643
Joined: 01 Sep 2017, 22:13
Location: the Netherlands
Contact:

Re: Two advice please - *.ino development

#15 Post by TD-er » 02 Nov 2019, 21:53

Everything you save to the Settings struct (PCONFIG is an alias for parts of the settings) is stored in the settings.
However the settings are lost when you reboot.
So what you have to do is call the command "save", the same way you do give the command you created.

Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot] and 41 guests