body:
I have a Firmata sketch, that accepts string messages, partitions them and sends its' parts back to a Firmata client program. My problem is certainly at the sketch's side. The problem is that `Firmata.sendString(argument1)` and `Firmata.sendString(argument2)` methods don't send anything. More information is found in the sketch's code. How can I get the `sendString` methods to work?

```lang-CPP
/*
 * This sketch accepts strings in the following form:
 * CMDn(arg1,arg2)
 * CMDn — command name,
 * arg1 и arg2 — unnecessary arguments.
 * Each argument's length can be from 1 to 4 characters,
 * They're saved to separate variables.
 *
 * This sketch sends back the parsed commands partially:
 * the command name, argument #1 (if present), argument #2 (if present)
 */

#include <Firmata.h>

void stringCallback(char *received) {
  //CMDn(arg1,arg2)
  //CMDn(arg1)
  //CMDn(1)
  //CMDn()
  //012345678901234
  //          11111

  //This scheme up there is just for
  //understanding the indexes of the chars in the string
  //in its various possible variations

  //Let's declare all the necessary variables
  char methodName[5];
  char argument1[5];
  char argument2[5];
  byte commaLocation = 0;

  //If the received string doesn't match the strings' syntax,
  //send an error message
  if (!(received[4] == '(' && strlen(received) <= 15)) {
    Firmata.sendString("ERR;");
    return;
  }

  //Let's take the 0-3 chars in the string and send it back.
  //It's probably the command name
  for (int i = 0; i < 4; i++) {
    methodName[i] = received[i];
  }
  methodName[4] = '\0'; //does or doesn't the compiler add the terminator automatically?
  Firmata.sendString(methodName); //send it
  //This string is being sent without problems.

  //If there is some arguments in the string,
  //it is detectable if the string char 5 is not ')'/
  if (received[5] != ')') {
    //Lent's find out if the input string has a `comma`
    //inside the parentheses. If it does, it means that
    //there are two arguments in the string.

    Firmata.sendString("46 passed");
    for (int i = 6; i < (strlen(received) - 1); i++) {
      //If there is a comma, save its' index and break the loop
      if (received[i] == ',') {
        commaLocation = i;
        break;
      }
    }

    //If a comma is not present, its location variable equals 0,
    //sincerely we just collect all the chars between the parentheses
    //to the 'argument1' variable and send it.
    if (commaLocation == 0) {
      Firmata.sendString("61 passed");
      for (int i = 5; i < ; i++) {
        argument1[(i - 5)] = received[i];
      }

      argument1[strlen(argument1)] = '\0'; //Either this is executed or not, the outcome doesn't change

      Firmata.sendString(argument1); //This very command doesn't work. It just does not send anything.
                                     //Looks like 'argument1' is empty, but I'm awfully sure that it must
                                     //not be empty. Anyway, the 'argument1' does not show up in the client
    }

    //If there is a comma present, then write chars before the comma
    //to 'argument1', and after the comma - to 'argument2'
    if (commaLocation != 0) {
      Firmata.sendString("77 passed");
      //let's write what is before the comma:
      for (int i = 5; i < commaLocation; i++) {
        argument1[i - 5] = received[i];
        Firmata.sendString("81 iterator");
      }

      //let's write what's after the comma;
      char argument2[5];
      for (int i = (commaLocation + 1); i < (strlen(received)); i++) {
        argument2[(i - (commaLocation + 1))] = received[i];
        Firmata.sendString("87 iterator");
      }

      argument1[strlen(argument1)] = '\0'; //Either this is executed or not, the outcome doesn't change
      argument2[strlen(argument2)] = '\0';

      Firmata.sendString(argument1); //Not working
      Firmata.sendString(argument2); //Not working
    }
  }
}

void sysexCallback(byte command, byte argc, byte *argv) {
  Firmata.sendSysex(command, argc, argv);
}

void setup() {
  Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);
  Firmata.attach(STRING_DATA, stringCallback);
  Firmata.attach(START_SYSEX, sysexCallback);
  Firmata.begin(57600);
}

void loop() {
  while (Firmata.available()) {
    Firmata.processInput();
  }
}
```

Expected output:

| What I send | What I receive (excluding the debug messages, `;` stands for newline) |
| ----------- | ------------------------------------------ |
| `DHTt()` | `DHTt` |
| `DHTt(1)` | `DHTt`; `1` |
| `DHTt(1,2)` | `DHTt`; `1`; `2` |

Real output:

| What I send | What I receive (excluding the debug messages) |
| --------    | -------------- |
| `DHTt()`    | `DHTt` *as long as there are no arguments, there are no problems. But the arguments are necessary for my task* |
| `DHTt(1)` | `DHTt` *the argument are not sent* |
| `DHTt(1,2)` | `DHTt` *two arguments are not sent neither* |

title: Firmata.SendString doesn't work with specific `char` variables

Answers: 2

body:
Here's a simplified version of your command parser using cstrings and pointers:

```
void parseArgs(char * rec){
  char cmd[32];
  char arg1[32]= {0};
  char arg2[32]= {0};
  char * ptr; // this is a re-usable workhorse pointer
  char * ptrDelim; // another workhorse to split arguments

  // first copy all of it to cmd
  strcpy(cmd, rec);
  // find end of command
  ptr = cmd;
  while( isalpha(ptr[0]) ) ptr++;
  ptr[0] = '\0'; // mark end of command string

  // find first arg
  ptr = strchr(rec, '(')+1; // set ptr to char to right of open paren
  strcpy(arg1, ptr); // copy stuff after open paren to arg1:
  ptr = strchr(arg1, ')');// find max extent of arg1
  if(ptrDelim=strchr(arg1, ',')){
    ptrDelim[0]='\0'; // end arg1's string at delim
    ptrDelim++; // move right one char
    strcpy(arg2, ptrDelim); // copy stuff after comma
    arg2[strlen(arg2)-1] = '\0'; // chop off ")"
  }else{
    ptr[0]='\0';
  }//end if comma?

 Serial.println("\nGiven:" + String(rec)+";");
 Serial.println("Command:" + String( cmd )+";");
 Serial.println("Arg1:" + String( arg1 )+";");
 Serial.println("Arg2:" + String( arg2 )+";");

}
```

Examples:

    parseArgs("CMDn()");
    parseArgs("CMDn(arg1)");
    parseArgs("CMDn(arg1,arg2)");

body:
`Firmata.sendString` does not send anything to the client in two cases:
- If the message is empty;
- **If the message does not contain the `\0` terminator in it**.

In this case, while you're sending `methodName`, you're manually assigning the terminator to the string; and the sender works:
```c++
methodName[4] = '\0';
```

The only thing necessary to do to solve this argument problem is making each `char` variable end with a null terminator. Here you can see the solved code:
```c++
#include <Firmata.h>

//setup() and loop() won't be here, there are no changes in them

unsigned long charIndex(const char * findIn, unsigned int symbol) {
  //Find 'symbol' in char array 'findIn'. Unlike
  //strchr(), returns unsigned long or 0 if 'symbol' not found

  char * pointer = strchr(findIn, symbol);
  if (pointer != NULL) return (pointer - findIn);
  if (pointer == NULL) return 0;
}

void stringCallback(char *received) {
  //Let's declare all the necessary variables
  char methodName[5];
  char argument1[5];
  char argument2[5];
  int commaLocation = 0;
  int lasti;

  byte nullTerminatorIndex = strlen(received); //For understanding

  //If the received string doesn't match the strings' syntax,
  //send an error message
  if (!(received[4] == '(' && strlen(received) <= 15)) {
    Firmata.sendString("ERR;");
    return;
  }

  //Let's take the 0-3 chars in the string and send it back.
  //It's probably the command name
  for (int i = 0; i < 4; i++) {
    methodName[i] = received[i];
  }
  methodName[4] = '\0'; //**The compiler doesn't add terminators automatically**.
  Firmata.sendString(methodName); //send it
  //This string is being sent without problems.

  //If there is some arguments in the string,
  //it is detectable if the string char 5 is not ')'/
  if (received[5] != ')') {
    //Lent's find out if the input string has a `comma`
    //inside the parentheses. If it does, it means that
    //there are two arguments in the string.

    Firmata.sendString("46 passed");
    if (charIndex(received, ',') != 0) commaLocation = charIndex(received, ',');

    //If a comma is not present, its location variable equals 0,
    //sincerely we just collect all the chars between the parentheses
    //to the 'argument1' variable and send it.
    if (commaLocation == 0) {
      Firmata.sendString("61 passed");
      for (int i = 5; i < (nullTerminatorIndex - 1); i++) {
        argument1[(i - 5)] = received[i];
        lasti = (i - 5);
      }

      argument1[(lasti + 1)] = '\0';
      lasti = 0;

      Firmata.sendString(argument1);
    }

    //If there is a comma present, then write chars before the comma
    //to 'argument1', and after the comma - to 'argument2'
    if (commaLocation != 0) {
      Firmata.sendString("77 passed");
      //let's write what is before the comma:
      for (int i = 5; i < commaLocation; i++) {
        argument1[i - 5] = received[i];
        lasti = (i - 5);
      }

      argument1[(lasti + 1)] = '\0';
      lasti = 0;

      //let's write what's after the comma;
      char argument2[5];
      for (int i = (commaLocation + 1); i < (nullTerminatorIndex - 1); i++) {
        argument2[(i - (commaLocation + 1))] = received[i];
        lasti = (i - (commaLocation + 1));
      }

      argument2[(lasti + 1)] = '\0';
      lasti = 0;

      Firmata.sendString(argument1);
      Firmata.sendString(argument2);
    }
  }
}
```


body:
I want to connect this [analog Vernier temperature probe][1] to my Arduino with this [British Telecom Connector (BTA)][2].

According to datasheet, when sensor is in the connector, the PIN 6 of the connector should give us the value from 0-5V. I think it should work with this connector because it is supposed to work with [this adapter][3], which is approved by Vernier. It's hard to get any real details about this official Vernier adapter, but I think it doesn't do anything different than just the BTA (linked above).

Of course, I also connected 5V and GND to connector, but when I want to read that 0-5V from Arduino, it says 0. Every single time. The sensor is not broken, because it works with Vernier sensor interface shield which I put on the Arduino (yes, I could use it, but I want to make my project smaller).

That's how the PINS work:

|Sensor Pin                   |Arduino Pin             |
|-----------------------------|------------------------|
|1 (+/-10 V output line)      |A1                      |
|2 (Ground)                   |Ground                  |
|3 (Vres/resistance reference)|A4 (also for I2C autoID)|
|4 (AutoID)                   |A5 (also for I2C autoID)|
|5 (+5 Volt power)            |5V                      |
|6 (0-5 V output line)        |A0                      |

I don't know if that's important, but the sensor is based on a thermistor. Also, if I connect `A0` to PIN number 1 (+/- 10V output line), it gives me a value.  But, I really can't find anywhere how is that value connected with temperature. I hope I presented my problem well enough so you will understand it.

Thanks :)

  [1]: https://www.vernier.com/product/stainless-steel-temperature-probe/
  [2]: https://www.sparkfun.com/products/12753
  [3]: https://www.vernier.com/product/analog-protoboard-adapter/

title: Vernier to Arduino not working

Answers: 0


body:
I have an Arduino Due that was programmed by the Arduino IDE, to cut things short I lost access to the original sketch (.ino) file, there is no way of recovering it no matter what.

I know that in the 8-bit MCUs I can read the .hex file from the flash memory, I already did that with PIC and AVR MCUs with their software programmer utilities.

My question is: Can I use a software programmer utility on Windows PC to extract the hex file to reprogram other Arduino Due with it? If yes, please help me.
I've read about the Bossac utility, it looks promising, but I have no experience in the ARM MCUs field at all.

again: I am NOT interested in C or Assembly code, I just want the .hex file.

title: Extracting .hex from Arduino Due

Answers: 1

body:
You can use JTAG and probably should.  But, it can also be done with bossac *if* you are **very** careful.  If you're not, you'll end up erasing your flash on your source board.

Using bossac
==============

This would maybe not be preferred over JTAG because it is probably easier to screw up (see warnings below), but it can be done.  I may add some on JTAG programming later, and if I do it may be above this section for that reason.  The main advantage here is just that you don't need a JTAG programmer.  The one caveat is that your existing sketch, or rather the image of the sketch that has been burned onto what I'm calling the "source board" has to be functioning well enough that it can cooperate in being placed back into the ROM bootloader.  I fully expect this is not a problem for you, or for pretty much any normal Arduino sketch that has been burned to a board.

WARNINGS
--------

* Under **NO circumstances** do you want to connect to the **PROGRAMMING port** of your **source board** at **1200** baud.
Doing so **will erase your board**, and then that's the end of it.

* In the below you *will* be connecting to the *Native USB* port at 1200, **NOT** the programming port.
**Connect only one port** at a time to your computer so there is no possibility of selecting the wrong one.

* **Practice** this whole procedure with a board you don't care about **first**.

Locate your BOSSAC command.
---------------------------

On my Windows machine, it was in:
```none
C:\Users\username\AppData\Local\Arduino15\packages\arduino\tools\bossac\1.6.1-ardunio\bossac.exe
```

It may be under a different version number.  It's possible that it will be in a completely different location.

```cmd
cd %USERPROFILE%
dir bossac.exe /s/b/p/a
```
Should locate it it, eventually, in any case.

On Linux it will be under ~/.arduino15 somewhere:

```sh
find ~/.arduino15 -name bossac
```

On a Mac it will probably be under a /Library/ directory under the user account somewhere.  You get the idea, locate it, make sure you can run it.

NOTE: There's a bossa program that is the GUI version where bossa**c** is a command-line program.  Unfortunately the IDE board support files don't ship the GUI program.  If you're having trouble with the command-line and want to try that instead, go for it.  But test it on a board you don't care about beforehand.  I have not tried it.

Connect to the Native Header
----------------------------

Connect your native USB port on the source board and only to that port.
[![Picture indicating native USB port][1]][1]

Enable boot to ROM
------------------

Open a terminal emulator of your choice at a rate of 1200 baud to the native USB port, wait a couple seconds and then close the port.  You can use the Serial Monitor from the IDE to do this if you want:

* Select the correct port from Tools/Port.

* Open the Serial Monitor

* Switch the baud rate to 1200 baud.

* You're not going to type anything and you're not going to see anything once you're connected at 1200 baud.

* Close the Serial Monitor

* You probably should:

  * See if the port has changed COM#, if so select the new one.

  * Re-open the serial monitor

  * Change the baud rate again to anything-but-1200-baud

  * Close the serial monitor again.
    This is not strictly necessary but the IDE remember the last chosen baud rate, and for what we're doing this is a slightly dangerous thing.

* Close the IDE as well.

What [connecting at 1200 baud][2] does is activate the code inside the core part of the programmed sketch that [changes the board to boot from the internal ROM bootloader][3].  It doesn't need traffic.  It just needs to see a request for 1200 baud.  More specifically, it needs to see the DTR "signal" go inactive, which happens when the port is closed, when the effective rate was 1200 baud.

NOTE: if you **screw up** here and connect to the programming port at 1200 baud instead, you'll wind up [causing the ATMega16U2 to **erase**][4] **your source board**.  The IDE remembers your last chosen baud rate, which makes this easy to screw up as well.  Hence the weird little dance in the above instructions regarding reopening the serial monitor and changing to something other than 1200 baud.  It's just putting an extra barrier up to accidentally doing this.

Once you've connected to the native USB port at 1200 baud and closed the port, your board will not run your sketch any more.  It's still there, it's just not running it.  The board has been told to sit in the ROM based bootloader, waiting for bootloader commands.

Saving your existing sketch's image
-----------------------------------

What we're going to do is run the bossac command you found earlier like so:

```cmd
bossac --read saved-sketch-image.bin --boot --reset
```

I'm assuming you either changed directory to where bossac.exe is, or alternately you're going to specify the necessary path to it found earlier.  I've found this command locates the correct COM port automatically.

This command:

* Downloads all of flash, 512 kbyte, and takes while, 128 seconds in one test.  Weirdly the same version under Linux takes closer to 10 seconds;  I haven't looked into why the difference, but I'm also unconcerned.
So **you now should have a 512 kbyte raw binary file containing your sketch image.**

* It re-enables the boot-from-FLASH so that on the next reset it will go back to running your sketch

* It resets your board, so it will begin running your old sketch.  If you don't want it to do that until you power cycle it, you could just as easily leave off the `--reset` part.

*As said, this is a raw binary file.  But you mentioned a HEX.  I'm assuming you didn't mean that literally, so I'm not going to detail how to convert the .bin file to a HEX format.  Though, if you want to do that, you should know that it needs to be offset to 0x80000, because that's where flash starts on the Due.*

Disconnect your source board from USB.

Making your clone (target) board
--------------------------------

Connect to your target board via the programming port.

[![Picture indicating connection to target board's programming port][6]][6]

* Hold the erase button for a few seconds to make sure the target board is erased.  Usually this would be done by the IDE connecting to the port for a while at 1200 baud.  But since we're using bossac at the command line, we need to do that step manually; it's just easier to use the button this time.

* Reset the board with the reset button.  Your target board is now sitting in its ROM bootloader awaiting commands.

* Put your image on the new board with:
```cmd
bossac --write saved-sketch-image.bin --boot --reset
```

*  Again, it's programming the whole 512 kbytes.  In one test on Windows it took about 100 seconds; no difference between Windows and Linux.  We're using the USART (programming port) which is slower than USB and we're flashing rather than reading which is slower; I haven't bothered to figure out which thing is the bottleneck.

* Like before `--boot` sets the board to boot from flash (your sketch) on next reset.

* And again `--reset` just resets the board.

Your target board should now be be behaving identically to the original source board.

  [1]: https://i.stack.imgur.com/wLRrs.jpg
  [2]: https://github.com/arduino/ArduinoCore-sam/blob/0840aa/cores/arduino/USB/CDC.cpp#L136
  [3]: https://github.com/arduino/ArduinoCore-sam/blob/0840aa277a7a6519147fcf041b0b3c5ae5dcbac1/cores/arduino/Reset.cpp#L31
  [4]: https://github.com/arduino/ArduinoCore-sam/blob/0840aa277a7a6519147fcf041b0b3c5ae5dcbac1/firmwares/atmega16u2/arduino-usbserial/Arduino-usbserial.c#L302
  [5]: https://i.stack.imgur.com/aZNvN.jpg
  [6]: https://i.stack.imgur.com/yPjSj.jpg


body:
Good afternoon guys!
I have a radio receiver connected to an arduino and I want it not to work all the time, but to turn on by the arduino timer for a certain time, and the rest of the time the receiver must be turned off by software.
I have a working sketch that allows you to tune this receiver, and it also allows you to re-tune the receiver (set the volume and frequency) by calling a function.

    #include <Wire.h>

    #define RDA5807M_RANDOM_ACCESS_ADDRESS 0x11
    // registers
    #define RDA5807M_REG_CONFIG 0x02
    #define RDA5807M_REG_TUNING 0x03
    #define RDA5807M_REG_VOLUME 0x05
    // flags
    #define RDA5807M_FLG_DHIZ 0x8000
    #define RDA5807M_FLG_DMUTE 0x4000
    #define RDA5807M_FLG_BASS 0x1000
    #define RDA5807M_FLG_ENABLE word(0x0001)
    #define RDA5807M_FLG_TUNE word(0x0010)
    //masks
    #define RDA5807M_CHAN_MASK 0xFFC0
    #define RDA5807M_CHAN_SHIFT 6
    #define RDA5807M_VOLUME_MASK word(0x000F)
    #define RDA5807M_VOLUME_SHIFT 0
    #define RDA5807M_RSSI_MASK 0xFE00
    #define RDA5807M_RSSI_SHIFT 9

    //uint8_t volume; // 0..15
    //uint16_t freq = 1077; // 107.3FM
    uint16_t reg02h, reg03h, reg05h, reg0Bh;

    void setup() {
      Serial.begin(9600);
      Nastroika(1, 4, 1077); // Receiver setting: incl. or off (on, off), volume (0 ... 15), frequency MHz * 10 (107.7 = 1077)
    }

    void loop() {
      Nastroika(1, 4, 1077);
      delay(5000);
      Nastroika(0, 4, 1077); // Nastroika(0)
      delay(5000);
    }

    void setRegister(uint8_t reg, const uint16_t value) {
      Wire.beginTransmission(0x11);
      Wire.write(reg);
      Wire.write(highByte(value));
      Wire.write(lowByte(value));
      Wire.endTransmission(true);
    }

    uint16_t getRegister(uint8_t reg) {
      uint16_t result;
      Wire.beginTransmission(RDA5807M_RANDOM_ACCESS_ADDRESS);
      Wire.write(reg);
      Wire.endTransmission(false);
      Wire.requestFrom(0x11, 2, true);
      result = (uint16_t)Wire.read() << 8;
      result |= Wire.read();
      return result;
    }

    void Nastroika(byte Key, uint8_t volume, uint16_t freq) // Receiver configuration after power failure
    {
      Wire.begin();
      // Регистр 02h - inclusion, settings
      if (Key == 1)
      {
        reg02h = reg02h | RDA5807M_FLG_ENABLE | RDA5807M_FLG_DHIZ | RDA5807M_FLG_DMUTE;
      }
      else if (Key == 0)
      {
        reg02h = reg02h & ~RDA5807M_FLG_ENABLE | RDA5807M_FLG_DHIZ | RDA5807M_FLG_DMUTE;

      }
      setRegister(RDA5807M_REG_CONFIG, reg02h);
      // Регистр 03h - radio station selection
      // After reset in register 03h, the default value is 0
      // Thus BAND = 00 (87..108MHz), STEP = 00 (100kHz). Let's leave them as they are
      reg03h = (freq - 870) << RDA5807M_CHAN_SHIFT; // chan = (freq - band) / space
      setRegister(RDA5807M_REG_TUNING, reg03h | RDA5807M_FLG_TUNE);

      //Register 05h. Set the volume, do not change the rest of the beats
      reg05h = getRegister(RDA5807M_REG_VOLUME); // Reading the current value
      reg05h &= ~RDA5807M_VOLUME_MASK; // Resetting the bits VOLUME
      reg05h |= volume << RDA5807M_VOLUME_SHIFT; // Setting a new volume
      setRegister(RDA5807M_REG_VOLUME, reg05h);
    }

I need to modify this sketch and add the ability to wake up the receiver and put it into sleep mode. There is "RDA5807M_FLG_ENABLE" here. As I understand it, you need to change it?

*Added later:*

The method of turning off the receiver for a while, suggested in the comments, works.
However, for everything to be correct, when calling the function when the receiver is disconnected, we will send **Nastroika(0, 4, 1077);** that is, when turning off, we still specify the volume and frequency, although these parameters are superfluous here. It would be correct to write simply **Nastroika(0);** , But this cannot be done just like that, because there should be exactly three input arguments for the function, and not one.

title: Receiver sleep mode RDA5807M

Answers: 1

body:
Switch off:

    reg02h = reg02h & ~RDA5807M_FLG_ENABLE;
    setRegister(RDA5807M_REG_CONFIG, reg02h);

Switch on:

    reg02h = reg02h | RDA5807M_FLG_ENABLE;
    setRegister(RDA5807M_REG_CONFIG, reg02h);

**EDIT:** (to answer a comment of Антон)

Nastroika (настройка) means "tuning". Is that right? Then I would use this method only for tuning. Create two methods one for switching off and one for switching on.

    void switchOff()
    {
       reg02h = reg02h & ~RDA5807M_FLG_ENABLE;
       setRegister(RDA5807M_REG_CONFIG, reg02h);
    }

    void switchOn()
    {
       reg02h = reg02h | RDA5807M_FLG_ENABLE;
       setRegister(RDA5807M_REG_CONFIG, reg02h);
    }

In the `Nastroika` Method you should only perform the tuning and let the module of. If you insist to switch on at the same time you could use your old version.

Example:

    void Nastroika(uint8_t volume, uint16_t freq)
    {
       // !!!!! This is the wrong place for Wire begin
       // move it to the setup method.
       // Wire.begin();
       reg02h = reg02h | RDA5807M_FLG_DHIZ | RDA5807M_FLG_DMUTE;
       // or if you insist / you want to keep the module be started here
       // reg02h = reg02h | RDA5807M_FLG_ENABLE | RDA5807M_FLG_DHIZ | RDA5807M_FLG_DMUTE;
       setRegister(RDA5807M_REG_CONFIG, reg02h);
       reg03h = (freq - 870) << RDA5807M_CHAN_SHIFT;
       setRegister(RDA5807M_REG_TUNING, reg03h | RDA5807M_FLG_TUNE);

       reg05h = getRegister(RDA5807M_REG_VOLUME);
       reg05h &= ~RDA5807M_VOLUME_MASK;
       reg05h |= volume << RDA5807M_VOLUME_SHIFT;
       setRegister(RDA5807M_REG_VOLUME, reg05h);
    }

Usage:

    void setup()
    {
       Serial.begin(9600);
       Wire.begin();
       Nastroika(4, 1077);
    }

    void loop()
    {
      switchOff();
      delay(5000);
      switchOn();
      delay(5000);
    }


body:
I have build a couple of boards that have an ATMEGA328P-AU (the 32 pin MLF, as used on the Arduino Pro Mini). If I burn a bootloader via SPI to use an external 8MHz clock, I can then use the Arduino IDE to write a program via the serial port. If I burn a bootloader to use an internal 8MHz clock, burning the bootloader is still successful but programming with the Arduino IDE does not work.

The current boards do have crystals, but I want to build the rest of the boards without a crystal, so I need to get internal clock working.

The internal (non-working) script looks like this:

    avrdude -Cavrdude.conf -v -patmega328p -B4 -cusbasp -Pusb -Ulock:w:0x3F:m -Uefuse:w:0xFD:m -Uhfuse:w:0xDA:m -Ulfuse:w:0xE2:m
    avrdude -Cavrdude.conf -c usbasp -p atmega328p -e -Uflash:w:ATmegaBOOT_168_atmega328_pro_8MHz.hex

The external (working) script looks like this:

    avrdude -Cavrdude.conf -v -patmega328p -B4 -cusbasp -Pusb -Ulock:w:0x3F:m -Uefuse:w:0xFD:m -Uhfuse:w:0xDA:m -Ulfuse:w:0xFF:m
    avrdude -Cavrdude.conf -c usbasp -p atmega328p -e -Uflash:w:ATmegaBOOT_168_atmega328_pro_8MHz.hex

By my reckoning, lfuse=0xE2 should be CKDIV8=1, CKOUT=1, SUT=10 and CKSEL=0010.

Any suggestions how to make the internal clock work?

title: Cannot program ATMEGA328PU after burning bootloader with internal clock

Answers: 0


body:
When a button is pressed, the Arduino might be busy with something (like drawing the screen). When the Arduino has finally time to check the button input, the uses might have release it already.

Is there a way that can store the input until the Arduino has time to check it?
It would be awesome if there was ic that could take care of this.

Thanks for the help!

title: Memory for inputs?

Answers: 3

body:
The basic guidance when writing Arduino applications is to do a small amount of work on every pass through the loop function, then do a little bit more on the next pass. Check all your inputs, execute logic in response to those inputs, set up `unsigned long` variables with future `millis()` values, check those values to see if a future time has arrived, and repeat.

Do **not** use `delay()`. It is the death of a cooperative system like an Arduino. When your Arduino executes a call to `delay()`, everything stops until the delay time has passed.

body:
> Is there a way that can store the input until the Arduino has time to check it?

No, there is no way to remember/buffer input changes within the Arduino (You could use a flipfop IC like JRobert wrote. That can give you that functionality). But there are interrupts, that you can use with pins. A triggered interrupt will really interrupt the main code from running and execute its corresponding ISR (Interrupt Service Routine), to handle the interrupt cause, and then returning to execute the main code. A microcontoller has many different interrupts, each one connected to its special hardware. There are interrupts for the Serial interface, for SPI, I2C, and also some connected to the External Interrupt pins or the PinChange Interrupt (these last two could be used with your button). So this would not "store" the input change, but it will interrupt the main code to immediately act upon the input change. So that's a different principle.

If you want to bind your button to an interrupt, you could just stay in the Arduino Framework and use the `attachInterrupt()` function. There are many tutorials online for that. Keep in mind, that you should never do long things inside an ISR, and functions like `delay()` won't work there.

---

That said, most likely it is not really needed to use interrupts with buttons. Humans are rather slow, thus each button press will last in the ballpark of 100ms or longer.

You could now say, that your code is doing things longer than 100ms. But here the rabbit is buried (literal translation of a german saying, meaning "there is the problem"). When starting with Arduino, one is doing many blocking things, like `delay()` or blocking while loops. These are often very easy to implement, but nothing else will be running during these things.

Instead you should divide up your actions into small parts. When it is time to do something, you are doing that small part and exit fast. This enables other code to run in between. A good example is the `BlinkWithoutDelay` example. The normal blink example uses `delay()`, which blocks everything else. Instead you can use the `millis()` function as a clock and only take action, when it is time to do so, otherwise to further fast. Much like you would bake a pizza in your oven. You won't sit in front of the oven, waiting for the pizza to be ready. You would do something else and regularly look at your clock, if it is time to take the pizza out.

You didn't show your code, so we cannot advice you more in that direction. But you can find many tutorials about it, if you search for terms like `Arduino blink without delay` or `Arduino millis tutorial`.

body:
The answer to your direct question, is there an IC to store an input, is yes. It's called a Set-Reset (or SR) Flip-Flop. I don't know if they're packaged standalone in an IC but they're really simple to make with a pair of [cross-connected NAND gates][1].

But that's not really the right solution to your problem. Your code should not be so "busy" that it misses a slow input like a push-button. I quoted "busy" because it is usually delay() calls, not computations, that occupy the processor for any large amounts of time, and delay()s are to be avoided if your code has any more than 1 thing to do.

Look up the Blink Without Delay example-sketch in the Arduino IDE for the unvarnished, basic approach to doing this. Then there are libraries that can help with the low-level details of doing it - [SimpleTimer][2], is one such. Or, if your code is stuck waiting for slow external events, don't wait for them but check for them frequently and move on immediately to something else, if they haven't taken place yet.

  [1]: https://circuitglobe.com/rs-flip-flop.html#TheNANDGateRSFlipFlop
  [2]: https://github.com/jfturcot/SimpleTimer/blob/b30890b8f7046bf3b0258e5870e5dda78ac5c71a/SimpleTimer.cpp


body:
Here I wrote code for my weighting scale measurement. In which I added an on/off switch for my LCD display. But in defined delay time my LCD is a blink and I do not want it. I want my LCD switch on/off work on 1000 delay time effectively.
How I can do this. please guide and edit my code.

    #include "HX711.h"
    #include <LiquidCrystal_I2C.h>

    HX711 scale(4, 5);//(DT, SCK)
    LiquidCrystal_I2C lcd(0x27, 16, 2);
    const int buttonPin = 2;
    int buttonState = 0;

    float calibration_factor = -55;
    float units;
    float ounces;
    float in_kg;

    void setup()
    {
      //  Serial.begin(9600);
      lcd.init();
      lcd.noDisplay();
      lcd.noBacklight();

      lcd.setCursor(0, 0);
      lcd.print("Calculate Weight");
      lcd.setCursor(0, 1);
      lcd.print("Loading...      ");
      delay(3000);

      scale.set_scale(calibration_factor);
      scale.tare();

    }

    void loop()
    {
      units = scale.get_units(), 10;
      if (units < 0)
      {
        units = 0.00;
      }
      ounces = units * 0.035274;
      in_kg = units / 1000;

      buttonState = digitalRead(buttonPin);
      if (buttonState == HIGH)
      {
        lcd.setCursor(0, 1);
        lcd.print("Reading: ");
        lcd.print(in_kg);
        lcd.print("kg");

        lcd.backlight();

        // Display the text on the LCD.
        lcd.display();

        delay(3000);
        lcd.noDisplay();
        lcd.noBacklight();

      }

    }

title: How to stop my 16*2 lcd blink?

Answers: 0


body:
The frequency should be increased by 100 Hz whenever an external push-button on UNO digital pin 5 is depressed and then released. I think I might missing something critical.
```
#define LEDPIN 3
float highTime;
float lowTime;
int freq;
float period;

//uint16_t val2= pulseIn(4, HIGH);

ISR(TIMER1_COMPA_vect) { digitalWrite(LEDPIN, !digitalRead(LEDPIN)); }
void setup() {
Serial.begin(9600);
pinMode(LEDPIN, OUTPUT);
// initialize Timer1 (the 16-bit timer) using channel A output compare

TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
TCNT1 = 0; // initialize counter value to 0
// set compare match register for 100 Hz increments
OCR1A = 9999; // = 16000000 / (8 * 100) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS12, CS11 and CS10 bits for 8 prescaler
 TCCR1B |= (0 << CS12) | (1 << CS11) | (0 << CS10);

// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
sei(); // allow interrupts
interrupts(); // enable global interrupts:
}
void loop() {

highTime =(pulseIn(4, HIGH));
lowTime=(pulseIn(4, LOW));
period = highTime+lowTime;
freq=1000000/period;       //getting frequency with totalTime is in Micro seconds
Serial.print(freq);
delay(1000);

Serial.print("\n");
```
Basically I want to turn the above code which display "100" in serial monitor with raises the frequency by 100 by a button press.

```
#define LEDPIN 3
const int buttonPin = 5;    // the number of the pushbutton pin

//uint16_t val2= pulseIn(4, HIGH);
// Variables will change:
int ledState = HIGH;         // the current state of the output pin
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin

// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

ISR(TIMER1_COMPA_vect) { digitalWrite(LEDPIN, !digitalRead(LEDPIN)); }
void setup() {
  Serial.begin(9600);
  pinMode(LEDPIN, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  // initialize Timer1 (the 16-bit timer) using channel A output compare

  TCCR1B = 0; // same for TCCR1B
  TCNT1 = 0; // initialize counter value to 0
  // set compare match register for 100 Hz increments
  OCR1A = 9999; // = 16000000 / (8 * 100) - 1 (must be <65536)
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS12, CS11 and CS10 bits for 8 prescaler
  TCCR1B |= (0 << CS12) | (1 << CS11) | (0 << CS10);

  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);
  sei(); // allow interrupts
  interrupts(); // enable global interrupts:

}
void loop() {
  int reading = digitalRead(buttonPin);
   // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer than the debounce
    // delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading != buttonState) {
      buttonState = reading;

      // only toggle the LED if the new button state is HIGH
      if (buttonState == HIGH) {
        ledState = !ledState;
      }
    }
    lastButtonState = reading;

    Serial.print(reading);
    delay(1000);
    Serial.print("\n");

  }
}
```

title: I am trying to up the frequency everytime button is press by 100 Hz, I am using the Input pull registor

Answers: 1

body:
Your button input pin is set to INPUT_PULLUP mode so that pin will always read HIGH unless you ground it. Your button should connect the pin to ground when it is pressed.

If you do that, then the pin will read HIGH when the button is not pressed, and LOW when the button is pressed. Near the bottom of your loop() function, you test the button and toggle the LED with:

      if (buttonState == HIGH) {
          ledState = !ledState;
      }

But this toggles the LED when the button is released. Is that really what you meant?


body:
sorry for the nooby question but I can't seem to find the answer to this anywhere, probably because I'm unsure what to search for with this problem!

I'm just wondering what the reason is for including a data type in brackets before a calculation takes place? In the code below, all the variables have already been declared at the top of the program, so I'm unsure what the reason / effect of including the (float) has. acc_y and angle_pitch_acc have been declared as floats and acc_total_vector has been declared as long

    angle_pitch_acc = asin((float)acc_y/acc_total_vector)* 57.296;

Thanks!

title: What is the purpose of putting a data type in brackets before a calculation?

Answers: 1

body: It's called *casting*. It changes the data type temporarily. In this instance it's being used to change an integer type into a floating point type, which means that the whole calculation is done using floating point mathematics. However `acc_y` is supposedly already a float, but maybe it wasn't at the time the author wrote that line. Maybe things, as they often do in a program, evolved. Only the author knows.


body:
I see there is a blue terminal connector an the tags below the PCB Vin, 5V, 3,3V and GND, but I am unsure where should I supply voltage to power up the board.
Also, in the product page it says the power can range from 6.5 to 11v, so what is those 5V and 3.3V all about?
Thanks

title: What is the pinout of the Arduino MKR motor carrier when using external power supply, not the Li-Po battery

Answers: 1

body:
`Vin` means "Voltage Input". That's where you provide your power. That is the input to the voltage regulator.

5V and 3.3V are what the board uses internally and are provided for you to also use should you want to. These are outputs from the voltage regulators.

It's exactly the same (though more efficient and higher current) as almost every other Arduino.


body:
I'm having a really strange problem with my screen. It's connected in i2c to my Arduino Nano and I'm using a rotary encoder to navigate through a menu.

At startup everything is fine, but when I change menus a couple of times, there are flickering artifacts that start showing up in the bottom right corner. Did anyone ever get that kind of localized noise?

I thought maybe it would be my refresh rate that was a bit too high, I only had 10ms. But I cranked it up to 50 and it didn't change a thing.

[https://youtu.be/riwLRgtHG0g][1]

EDIT: Thank you for your feedback! I tried a different approach, like you suggested, and got rid of all the calls to displayMenu() and the multiple while loops. The artifacts are smaller now, but they're still there...

They used to occur all the time and now they're just appearing during chooseValue() and action3() now. As if it was linked to the "value" variable. I don't get it...

Here's the updated code:

    #include <Arduino.h>
    #include <SPI.h>
    #include <Wire.h>
    #include <Adafruit_GFX.h>
    #include <Adafruit_SSD1306.h>
    #include <Adafruit_I2CDevice.h>
    #include <math.h>

    #include <RotaryEncoder.h>
    #include <ButtonStates.h>

    #define SCREEN_WIDTH    128
    #define SCREEN_HEIGHT   64
    #define OLED_RESET      -1                                                  // Reset pin # (or -1 if sharing Arduino reset pin)
    #define SCREEN_ADDRESS  0x3C

    Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

    RotaryEncoder encoder(A2, A3);                                              // Rotary encoder connected to A2 and A3
    ButtonSwitch button(2);                                                     // Rotary encoder button

    int value = 0;                                                              // Value changed in one of the menus
    int selection = 0;                                                          // Encoder position

    struct menuItem {                                                           // Structure defining a menu item
      const char *name;                                                         // Item name
      void (*action)();                                                         // Pointer pointing to the function handling the action
    };

    struct menu {                                                               // Structure defining a menu
      char *name;                                                               // Menu name
      int items;                                                                // Number of items in the menu
      struct menuItem *collection;                                              // Array containing all the menu items
    };

    struct menuItem menu1collection[5];                                         // Array for the menu
    struct menuItem item1, item2, item3, item4, item5;                          // Items of the menu
    struct menu menu1 = { "Today's menu", 5, menu1collection };                 // Structure holding all the menu's info

    struct menuItem menu2collection[4];
    struct menuItem item6, item7, item8, item9;
    struct menu menu2 = { "Tomorrow's menu", 4, menu2collection };

    struct menu currentmenu = menu1;

    enum screens { MENU, CHOOSEVAL };
    enum screens screen = MENU;

    void chooseValue(){
      display.clearDisplay();
      display.setTextSize(2);
      display.setTextColor(SSD1306_WHITE);
      display.setCursor(0, 20);
      display.write( 17 );
      display.setCursor(45, 20);
      display.print(selection);
      display.print("g");
      display.setCursor(115, 20);
      display.write( 16 );
      display.display();
    }

    void displayMenu(){                                                         // Function displaying the menu passed in argument
      display.clearDisplay();
      display.setTextSize(1);
      display.setTextColor(SSD1306_WHITE);
      display.setCursor(0, 5);
      display.println(currentmenu.name);                                        // Display menu title

      int div = floor((selection-0.5)/4);                                       // Handle menus with more than 4 elements

      for(int i=(4*div+1), j=0 ; i<=currentmenu.items && j<4 ; i++, j++){       // Cycle through 4 menu items
        if(i==selection){                                                       // Highlight selected item
          display.fillRect(0, 18+10*j, 128, 10, SSD1306_WHITE);
          display.setCursor(20, 20+10*j);
          display.setTextColor(SSD1306_BLACK);
          display.println(currentmenu.collection[i-1].name);
        }
        else{
          display.setTextColor(SSD1306_WHITE);
          display.setCursor(20, 20+10*j);
          display.println(currentmenu.collection[i-1].name);                    // Display item
        }
      }
      display.display();
    }

    ISR(PCINT1_vect) {                                                          // Interrupt routine for the rotary encoder
      encoder.tick();                                                           // Check the state of the encoder
    }

    // Functions handling the actions for each menu item ------------------------------------------------------------------
    void action1(){
      screen = CHOOSEVAL;
    }

    void action2(){
      currentmenu = menu2;
      encoder.setPosition(1);
    }

    void action3(){
      display.clearDisplay();
      display.setTextSize(2);
      display.setTextColor(SSD1306_WHITE);
      display.setCursor(45, 20);
      display.print(value);
      display.println("g");
      display.display();

      delay(1000);
    }

    void action4(){
      display.clearDisplay();
      display.setTextSize(2);
      display.setTextColor(SSD1306_WHITE);
      display.setCursor(0, 20);
      display.println("Action 4!");
      display.display();

      delay(500);
    }

    void action5(){
      display.clearDisplay();
      display.setTextSize(2);
      display.setTextColor(SSD1306_WHITE);
      display.setCursor(0, 20);
      display.println("Action 5!");
      display.display();

      delay(500);
    }

    void action6(){
      display.clearDisplay();
      display.setTextSize(2);
      display.setTextColor(SSD1306_WHITE);
      display.setCursor(0, 20);
      display.println("Action 6!");
      display.display();

      delay(500);
    }

    void action7(){
      display.clearDisplay();
      display.setTextSize(2);
      display.setTextColor(SSD1306_WHITE);
      display.setCursor(0, 20);
      display.println("Action 7!");
      display.display();

      delay(500);
    }

    void action8(){
      display.clearDisplay();
      display.setTextSize(2);
      display.setTextColor(SSD1306_WHITE);
      display.setCursor(0, 20);
      display.println("Action 8!");
      display.display();

      delay(500);
    }

    void action9(){
      currentmenu = menu1;
      encoder.setPosition(1);
    }
    // -------------------------------------------------------------------------------------------------------------------

    void handleMenu(){
    }

    void setup() {
      Serial.begin(9600);

      // Creating a menu requires the following ----------------------------------------------------------------------------
      item1.name = "Choose a value";
      item1.action = action1;
      menu1collection[0] = item1;

      item2.name = "Go to menu 2";
      item2.action = action2;
      menu1collection[1] = item2;

      item3.name = "Display value";
      item3.action = action3;
      menu1collection[2] = item3;

      item4.name = "Item 4";
      item4.action = action4;
      menu1collection[3] = item4;

      item5.name = "Item 5";
      item5.action = action5;
      menu1collection[4] = item5;

      item6.name = "Item 6";
      item6.action = action6;
      menu2collection[0] = item6;

      item7.name = "Item 7";
      item7.action = action7;
      menu2collection[1] = item7;

      item8.name = "Item 8";
      item8.action = action8;
      menu2collection[2] = item8;

      item9.name = "< Back";
      item9.action = action9;
      menu2collection[3] = item9;
      // -------------------------------------------------------------------------------------------------------------------

      PCICR |= (1 << PCIE1);                                                  // This enables Pin Change Interrupt 1 that covers the Analog input pins or Port C.
      PCMSK1 |= (1 << PCINT10) | (1 << PCINT11);                              // This enables the interrupt for pin 2 and 3 of Port C.

      if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {              // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
        Serial.println(F("SSD1306 allocation failed"));
        for(;;);                                                              // Don't proceed, loop forever
      }

      // Init display
      display.clearDisplay();
      display.setTextSize(2);
      display.setTextColor(SSD1306_WHITE);
      display.setCursor(0, 20);
      display.println("Loading...");
      display.display();

      delay(500);
    }

    void loop() {
      switch(screen){
        case MENU:
          selection = encoder.getPosition();                                      // Get the encoder's position

          if (selection < 1) {                                                    // Stop the encoder on the min position
            encoder.setPosition(1);
            selection = 1;

          } else if (selection > currentmenu.items) {                             // Stop the encoder on the max position (number of items minus 1)
            encoder.setPosition(currentmenu.items);
            selection = currentmenu.items;
          }

          displayMenu();

          if (button.triggerSingle()){
            currentmenu.collection[selection-1].action();                         // If a click is detected do the item's action
          }
          break;
        case CHOOSEVAL:
          selection = value + encoder.getPosition() * 10;

          if (selection < 1) {                                                    // Stop the encoder on the min position
            encoder.setPosition(1);
            selection = 1;
          }

          chooseValue();

          if (button.triggerSingle()){
            value = selection;
            encoder.setPosition(1);
            screen = MENU;
          }
          break;
      }
    }

  [1]: https://youtu.be/riwLRgtHG0g

title: Random artifacts on SSD1306 OLED screen

Answers: 1

body:
This is a solution that I accidentally came up with. I had a problem of strange artifacts corruption in bottom right corner of my SSD1306 display when I tried to print scrolled row of text.

It does its job, so if anyone come by this topic in the future feel free to test it:

    int x, minX;
    oled_dispMidTextScroll(F("SETPOINT REACHED! LONG PRESS LEFT TO SET UP A TIMER"));

    void oled_dispMidTextScroll(String str){
      char text[50];
      int size = 1;
      str.toCharArray(text, 50);
      display.setTextSize(size);
      minX = (-1 * size * 6) * strlen(text);  // 12 = 6 (px/char) * 2 (textsize)
      display.setCursor(x,28);
      display.print(text);
      x -= 4; // speed
      if (x < minX) {x = display.width();}
    }


body:
As an exercise to learn rather then the most efficient way to accomplish a goal.... (i'm a hands on hardware guy, but I need to get my Sh!T together and learn some coding)

I would like to make an LED less bright within a project.  I have a nano set up to control a relay to control a dc load when a momentary switch is pressed (this is kinda needlessly complicated solely to allow me to use a particular momentary switch I wanted to use for a bunch of not that great reasons ;-)

Anyway... the code i'm using is this:

```
int pbuttonPin = 2;// connect output to push button
int relayPin = 10;// Connected to relay (LED)

int val = 0; // push value from pin 2
int lightON = 0;//light status
int pushed = 0;//push status

void setup() {
  // Robojax.com code and video tutorial for push button ON and OFF
  Serial.begin(9600);
  pinMode(pbuttonPin, INPUT_PULLUP);
  pinMode(relayPin, OUTPUT);
 digitalWrite(relayPin, HIGH);// keep the load OFF at the begining. If you wanted to be ON, change the HIGH to LOW
}

void loop() {
// Robojax.com code and video tutorial for push button ON and OFF
  val = digitalRead(pbuttonPin);// read the push button value

  if(val == HIGH && lightON == LOW){

    pushed = 1-pushed;
    delay(100);
  }

  lightON = val;

      if(pushed == HIGH){
        Serial.println("Light ON");
        digitalWrite(relayPin, LOW);

      }else{
        Serial.println("Light OFF");
        digitalWrite(relayPin, HIGH);

      }

// Robojax.com code and video tutorial for push button ON and OFF

  delay(100);
```

The above code is straight up cut and paste... i'm clueless

I have a LED cathode on pin 10, (so i know the relay is on more easily from a distance).  however the application is on a boat, and at night it is too bright and distracting.  So i want to make the LED dimmer... I know I could add a larger value resistor, but i want to expand my understanding and would like suggestions on other ways PWM maybe....

cheers:

title: Make an LED less bright

Answers: 3

body:
There are two methods of dimming a LED : by PWM or by a limiting current resistor.
1. PWM code

        `//Initializing LED Pin
        int led_pin = 10;
        void setup() {
        //Declaring LED pin as output
                pinMode(led_pin, OUTPUT);
        }
        void loop() {
                analogWrite(led_pin, 127); // half intensity
                delay(5);
        }`
2. Hardware. Use following schematic
[![enter image description here][1]][1]

  [1]: https://i.stack.imgur.com/atpIK.png

body:
If you want to decrease the brightness in general, the easiest solution would in deed be to use a high value resistor.

If you want to use PWM - for example to change brightness programmatically - you just need to replace the calls to `digitalWrite(HIGH|LOW)` with calls to `analogWrite(x)` ([ref][1]), where `x` represents the duty cycle/brightness. The range of `x` depends on your microcontroller.

Note, that PWM (which is used by `analogWrite()`) only works on dedicated pins.
On the other side, there are microcontrollers wich have analog pin with a "true" analog output. On such an analog pin - though it is possible to use `analogWrite()` - the brightness will not be linear and have an offset, which makes it pretty much useless for dimming an LED.

  [1]: https://www.arduino.cc/reference/en/language/functions/analog-io/analogwrite/

body:
Follow this tutorial. It doesn't get any better than this.
https://www.arduino.cc/en/Tutorial/BuiltInExamples/Fade


body:
Is there a DTMF signal detection method in the smartphone [SIM] call?ex) keypad value or signal value [not frequency signal]

If you press the keypad button while you're on the phone with two iPhones, you don't hear the signal. So does the SAMSUNG phone.Please let me know how to detect DTMF signals after installing the aduino SIM.

Quectel EC25

title: SIM phone DTMF Signal Frequency Problem

Answers: 0


body:
I'm trying to use avrdude to load an Arduino program with the console, but I have a Windows 7 x86 Professional with Service Pack 1 (old PC).  When I install the Arduino driver that comes with the IDE manually, with pnputil.exe, in the Windows 7 on PCs that have these processors:

- Intel(R) Pentium(R) 4 CPU 2.80GHz
- Intel(R) Core(TM)2 Duo CPU E6400 @ 2.13GHz
- Intel(R) Core(TM)2 Duo CPU E8400 @ 3.00GHz

I see that the drivers don't work properly.  I get error code 22 in some cases.  And in other cases, the Windows system disables the Arduino in the Windows devices and prevents enabling the COM device.

But, if I install the Arduino IDE or manually install the Windows driver on Core i3, Core i5 and i7 in Windows 7, 8 , 10, the response is perfect.  But, in the others I get error code -22 or Windows doesn't allow to enabling the device.

Has anyone had the same problem and how did you solve it?

Thanks.

title: Windows Driver for Arduino error code 22

Answers: 0


body:
I have two Arduinos with identical wiring, they will (hopefully) end up being laser guns for my younger cousins.

When they both have a sketch which simply toggles lights when the correct IR code is received, everything works as it should. see the code here:

// Start of sketch 1

    #include <IRremote.h>
    IRsend irsend; //Setup the IR transmitter
    int receiver = 8; //initialize pin 13 as receiver pin.
    IRrecv irrecv(receiver); //create a new instance of receiver
    decode_results results;

    // declare consants
    const int trigger = 13;
    const int greenLight = 7;
    const int yellowLight = 2;
    const int timeBetweenTransmittion = 800;

    // declare variables
    bool toggleGreen = true;
    bool toggleYellow = true;
    long int previousTransmittion = 0;

    // put your setup code in here, to run once:
    void setup()
    {
      pinMode(trigger, INPUT_PULLUP);
      Serial.begin(9600); // send code at 9600 bits per second
      irrecv.enableIRIn(); // start the receiver
    }

    // put your main code in here, to run repeatedly:
    void loop() {
      if (not digitalRead(trigger) && millis() > previousTransmittion + timeBetweenTransmittion) // if the button is pressed and it's been enought time since the last transmittion
      {
        Serial.println("send!");
        irsend.sendNEC(1367857, 32); // send the code
        irrecv.enableIRIn(); // sending ir stops the receiver so start the receiver again
        previousTransmittion = millis(); // set the record for latest transmittion to the currnt time

        // toggle the yellow light
        digitalWrite(yellowLight, toggleYellow);
        toggleYellow = not toggleYellow;
      }

      if (irrecv.decode(&results)) { // if we have received an IR signal
        Serial.println (String(results.value, HEX)); //display HEX results
        if (String(results.value, DEC) == "1367857")
        {
          Serial.println("correct code");
          // toggle the green light
          digitalWrite(greenLight, toggleGreen);
          toggleGreen = not toggleGreen;
        }
        irrecv.resume(); // it stops the receiver when something's received so we muct resume the ir receiver
     }
    }

// End of sketch 1

The receiver is on pin 8 and, button on pin 13 and transmitting LED is always on pin 3.

No issues there.

However, when I use the same concepts on a larger-scale project, a strange problem occurs. Once one of the Arduinos has sent some IR, the receiver no longer works. After every line of code which sends IR, I follow it with `irrecv.enableIRIn();`, and after every time it receives code I have the line `irrecv.resume();`. I can't work out what the problem is. It's very long, but the full code is below:

// Start of code 2

    // include the library code:
    #include <LiquidCrystal.h> // For the LCD
    #include <IRremote.h> // For the IR communication
    #include <PCM.h> // For the audio output

    const unsigned char gunShot[] PROGMEM = {}; // In the program this contains a huge array of notes, I removed them to save space

    const unsigned char gunClick[] PROGMEM = {}; // In the program this contains a huge array of notes, I removed them to save space

    // Declare consants for pins
    const int rs = A0, en = A1, d4 = A2, d5 = A3, d6 = A4, d7 = A5; // State constants for all the pins used for the LCD
    const int trigger = 13;
    const int redLight = 7;
    const int magReader1 = 9;
    const int magReader2 = 10;
    const int speaker = 11;
    const int healButton = 12;
    const int receiver = 8;
    const int muzzle = 2;

    // Declare constants for gameplay
    const int timeBetweenShots = 800; //(in 1000ths of a second)

    const int healAmount = 100;

    const int medicAmmo = 16;
    const int assultAmmo = 31;
    const int sniperAmmo = 1;

    const int medicDamage = 30;
    const int assultDamage = 23;
    const int sniperDamage = 75;

    const int playerNumber = 4;

    // Declare all valiables
    int timesKilledByTeam1 = 0; // I would loved to have used an array here, but for some reason an array broke the program
    int timesKilledByTeam2 = 0;
    int timesKilledByTeam3 = 0;
    int timesKilledByTeam4 = 0;
    int timesKilledByTeam5 = 0;
    int timesKilledByTeam6 = 0;
    int timesKilledByTeam7 = 0;
    int timesKilledByTeam8 = 0;

    String receivedCode = ""; // Store the received code in a string variable
    bool gameDone = false;

    bool semiCanShoot = true;
    bool gunShouldClick = true;

    int health = 100;
    int gameMode = 1; // 1=TDM, 2=FFA, 3=LTS, 4=LPS
    bool respawn = true;
    int teamOrPlayer = playerNumber;
    int loadStatus; // 0 is no mag, 1 is mag1, 2 is mag2

    int mag1Ammo; // Current ammo in mag1
    int mag2Ammo; // Current ammo in mag2
    int maxAmmo; // Ammo in one mag for the selected class
    int damage; // Damage this player is inflicting per shot

    long int timeOfFlash = 0;
    long int timeOfMuzzle = 0;
    long int timeOfLastShot = 0;
    long int loopTimer = 0;

    int gameStartTime; // In seconds so no need for long int
    //int secondsRemaining;
    int gameDuration;

    int playerClass = 0; // 0=Medic, 1=Asult, 2=Snipr

    int shootCode;

    IRsend irsend; //Setup the IR transmitter
    IRrecv irrecv(receiver); //create a new instance of receiver
    decode_results results;
    LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

    void SetupClass()
    {
        switch (playerClass)
        {
            case (0):
              maxAmmo = medicAmmo;
              damage = medicDamage;
              break;
            case (1):
              maxAmmo = assultAmmo;
              damage = assultDamage;
              break;
            case (2):
              maxAmmo = sniperAmmo;
              damage = sniperDamage;
              break;
        }
        mag1Ammo = maxAmmo;
        mag2Ammo = maxAmmo;
    }

    // Define subroutines
    //void QuickDisplayUpdate(int ammo, int secondsRemaining, int loadStatus, int health) // During a game, to save unnecessary computation, only update the things that might have changed during the game
    void QuickDisplayUpdate()
    {
        lcd.setCursor(11,0);
        if((gameDuration - (millis() / 1000 - gameStartTime)) / 60 < 10)
        {
          lcd.print("0");
          lcd.setCursor(12,0);
        }
        lcd.print(String((gameDuration - (millis() / 1000 - gameStartTime)) / 60));

        lcd.setCursor(14,0);
        if((gameDuration - (millis() / 1000 - gameStartTime)) % 60 < 10)
        {
          lcd.print("0");
          lcd.setCursor(15,0);
        }
        lcd.print(String((gameDuration - (millis() / 1000 - gameStartTime)) % 60));

        lcd.setCursor(7,1); // Put the / in as it might have been removed from a previous "Reload!"
        lcd.print("/");

        lcd.setCursor(0,1);
        if (loadStatus == 0) lcd.print("Reload!");
        else if (loadStatus == 1)
        {
          lcd.print("Mag" + String(loadStatus) + ":");
          lcd.setCursor(5,1);
          if (mag1Ammo < 10)
          {
            lcd.print("0");
            lcd.setCursor(6,1);
          }
          lcd.print(String(mag1Ammo));
        }
        else
        {
          lcd.print("Mag" + String(loadStatus) + ":");
          lcd.setCursor(5,1);
          if (mag2Ammo < 10)
          {
            lcd.print("0");
            lcd.setCursor(6,1);
          }
          lcd.print(String(mag2Ammo));
        }

        lcd.setCursor(13,1);
        if(health < 100)
        {
          lcd.print(" ");
          lcd.setCursor(14,1);
          if(health < 10)
            {
              lcd.print(" ");
              lcd.setCursor(15,1);
            }
        }

        lcd.print(String(health));
    }

    void FullDisplayUpdate(int teamOrPlayer)
    {
        lcd.clear();
        lcd.setCursor(0,0);
        switch (gameMode)
        {
            case (1):
              lcd.print("TDM");
              break;
            case (2):
              lcd.print("FFA");
              break;
            case (3):
              lcd.print("LTS");
              break;
            case (4):
              lcd.print("LPS");
              break;
        }

        lcd.setCursor(3,0);
        lcd.print(String(teamOrPlayer));

        lcd.setCursor(5,0);
        switch (playerClass)
        {
            case (0):
              lcd.print("Medic");
              break;
            case (1):
              lcd.print("Asult");
              break;
            case (2):
              lcd.print("Snipr");
              break;
        }

        lcd.setCursor(11,0);
        if((gameDuration - (millis() / 1000 - gameStartTime)) / 60 < 10)
        {
          lcd.print("0");
          lcd.setCursor(12,0);
        }
        lcd.print(String((gameDuration - (millis() / 1000 - gameStartTime)) / 60) + ":");

        lcd.setCursor(14,0);
        if((gameDuration - (millis() / 1000 - gameStartTime)) % 60 < 10)
        {
          lcd.print("0");
          lcd.setCursor(15,0);
        }
        lcd.print(String((gameDuration - (millis() / 1000 - gameStartTime)) % 60));

        lcd.setCursor(0,1);
        if (loadStatus == 0) lcd.print("Reload!");
        else if (loadStatus == 1)
        {
          lcd.print("Mag" + String(loadStatus) + ":");
          lcd.setCursor(5,1);
          if (mag1Ammo < 10)
          {
            lcd.print("0");
            lcd.setCursor(6,1);
          }
          lcd.print(String(mag1Ammo));
        }
        else
        {
          lcd.print("Mag" + String(loadStatus) + ":");
          lcd.setCursor(5,1);
          if (mag2Ammo < 10)
          {
            lcd.print("0");
            lcd.setCursor(6,1);
          }
          lcd.print(String(mag2Ammo));
        }

        lcd.setCursor(8,1);
        if (maxAmmo < 10)
        {
          lcd.print("0");
          lcd.setCursor(9,1);
        }
        lcd.print(String(maxAmmo));

        lcd.setCursor(11,1);
        lcd.print("H:" + String(health));

    }

    void Play()
    {
      gameDone = false; // When the game starts, the game isn't done

      FullDisplayUpdate(teamOrPlayer); // Fully update the display before the game starts

      // Setup the shoot code
      if(damage > 9) shootCode = (String(teamOrPlayer) + String(damage) ).toInt();
      else shootCode = (String(teamOrPlayer) + "0" + String(damage)).toInt();

      // Wait until either a start or cancel code is recieved
      Serial.println("wait");
      receivedCode = "";
      //irrecv.enableIRIn(); // sending ir stops the receiver so start the receiver again
      while (receivedCode.length() != 2 && receivedCode.length() != 4)
      {
        if (irrecv.decode(&results))
        {
          receivedCode = String(results.value, DEC); // Store the received code in a variable when we have received an IR signal
          irrecv.resume(); // Remove the code
        }
      }

      Serial.println("code: " + receivedCode);

      gameStartTime = millis() / 1000; // Set the game start time in seconds

      if (String(receivedCode) == "50") // If the received code was starting code (50) then play
      {
          Serial.println("strt, dur: " + String(gameDuration) + "team: " + String(teamOrPlayer));

          while (gameDone == false) // Repeat until the game is done
          {
              //Serial.println("Game loop");

              CheckForIR(); // Check for an IR code as often as possible

              if (playerClass == 0) // Only check for heal button if they are a medic
              {
                if (not digitalRead(healButton) && millis() > timeOfLastShot + timeBetweenShots) // If they are pressing the heal button and it's been enought time since last shot
                {
                    Serial.println("heal bttn");
                    if (loadStatus == 1 && mag1Ammo == maxAmmo) // If mag1 is in and it's full
                    {
                        Serial.println("heal 1");
                        irsend.sendNEC((String(teamOrPlayer) + "00").toInt(), 32); // Send the heal code
                        //irrecv.enableIRIn(); // sending ir stops the receiver so start the receiver again
                        digitalWrite(muzzle, 1); // Turn on the muzzle flash
                        timeOfMuzzle = millis(); // Set the time of the muzzle turning on
                        //startPlayback(healShot, sizeof(healShot)); // Play  heal sound
                        mag1Ammo = 0; // Empty the current mag
                    }
                    else if (loadStatus == 2 && mag2Ammo == maxAmmo) // If mag2 is in and it's full
                    {
                        Serial.println("heal 1");
                        irsend.sendNEC((String(teamOrPlayer) + "00").toInt(), 32); // Send the heal code
                        //irrecv.enableIRIn(); // sending ir stops the receiver so start the receiver again
                        digitalWrite(muzzle, 1); // Turn on the muzzle flash
                        timeOfMuzzle = millis(); // Set the time of the muzzle turning on
                        //startPlayback(healShot, sizeof(healShot)); // Play  heal sound
                        mag2Ammo = 0; // Empty the current mag
                    }
                }
              }

              CheckForIR();

              if (not digitalRead(trigger) && (millis() > timeOfLastShot + timeBetweenShots)) // If the trigger is pulled and it's been long enough since last shot
              {
                  Serial.println("sht bttn");
                  if (loadStatus == 1 && mag1Ammo > 0) // If mag1 is in and it has ammo
                  {
                      if (playerClass != 0 || semiCanShoot == true) // They can shoot if they are on full auto or if semi can shoot
                      {
                          Serial.println("1 sht");
                          irsend.sendNEC(shootCode, 32); // Send the shoot code
                          irrecv.enableIRIn(); // Start the receiver
                          digitalWrite(muzzle, 1); // Turn on the muzzle flash
                          timeOfMuzzle = millis(); // Set the time of the muzzle turning on
                          mag1Ammo = mag1Ammo - 1; // Reduce ammo of current mag by one
                          semiCanShoot = false; // Once they have shot, they cannot shoot again if on semi mode
                          startPlayback(gunShot, sizeof(gunShot)); // Play shot
                          Serial.println("1 sht done");
                      }
                  }

                  else if (loadStatus == 2 && mag2Ammo > 0) // If mag2 is in and it has ammo
                  {
                      if (playerClass != 0 || semiCanShoot == true) // They can shoot if they are on full auto or if semi can shoot
                      {
                          Serial.println("2 sht");
                          irsend.sendNEC(shootCode, 32); // Send the shoot code
                          irrecv.enableIRIn(); // Start the receiver
                          digitalWrite(muzzle, 1); // Turn on the muzzle flash
                          timeOfMuzzle = millis(); // Set the time of the muzzle turning on
                          mag2Ammo = mag2Ammo - 1; // Reduce ammo of current mag by one
                          semiCanShoot = false; // Once they have shot, they cannot shoot again if on semi mode
                          startPlayback(gunShot, sizeof(gunShot)); // Play shot
                          Serial.println("2 sht done");
                      }
                  }

                  else if (gunShouldClick) // (If no mag in OR no ammo in the mag that's in) AND gun should click
                  {
                      Serial.println("clik");
                      startPlayback(gunClick, sizeof(gunClick)); // Play click sound
                      gunShouldClick = false; // Gun shouldn't click again until they releace trigger
                  }
                  timeOfLastShot = millis(); // Update the time of last shot
                  Serial.println("shot done");
              }

              CheckForIR();

              // Check for if the gun should click again and if player can shoot again if on semi mode
              if (digitalRead(trigger)) semiCanShoot = true; // If they are not holding the trigger, they can shoot again if on semi mode
              if (digitalRead(healButton) && digitalRead(trigger)) gunShouldClick = true; // If they are not holding the trigger or the heal button, the gun should click again when they do hold it again

              CheckForIR();

              // If the LEDs have been on for long enough, turn them off
              if (millis() > timeOfFlash + 50) digitalWrite(redLight, 0); // Turn off the red LEDs if they have been on for enough time
              if (millis() > timeOfMuzzle + 50) digitalWrite(muzzle, 0); // Turn off the muzzle if it's been on for enough time

              CheckForIR();

              if (millis() > loopTimer + 250) // Some things need to be done less often, so do that to save time so IR receive checks can be done more frequently
              {
                  loopTimer = millis();

                  QuickDisplayUpdate(); // Quick update the display after every loop

                  CheckForIR();

                  // Update the loadStatus variable depending on the mag detector inputs
                  if (!digitalRead(magReader1) && digitalRead(magReader2))
                  {
                      loadStatus = 1;
                      mag2Ammo = maxAmmo; // Refil mag2 if mag one is in
                  }
                  else if (!digitalRead(magReader2) && digitalRead(magReader1))
                  {
                      loadStatus = 2;
                      mag1Ammo = maxAmmo; // Refil mag1 if mag two is in
                  }
                  else loadStatus = 0;

                  CheckForIR();

                  // Check to see if the game has reached the time limit
                  if (gameDuration - (millis() / 1000 - gameStartTime) < 1)
                  {
                    Serial.println("tm up");
                    gameDone = true;
                  }
              }

          } // Game is done

      } // If the received code wasn't the starting code then cancel the game and return to waiting menu
    }

    void CheckForIR()
    {
      //Serial.println("check");
      //irrecv.enableIRIn(); // sending ir stops the receiver so start the receiver again
      if (irrecv.decode(&results)) // If there is a code
      {
          receivedCode = String(results.value, DEC); // Store the received code in a string variable
          Serial.println(receivedCode);
          irrecv.resume(); // Remove the code
          if (receivedCode.length() == 3) // If the received code has length 3, we have been shot
          {
              Serial.println ("shot"); //display shot code
              if (receivedCode.substring(0,1) != String(teamOrPlayer)) // Only continue if the shooter is on another team
              {
                  Serial.println ("another team");
                  digitalWrite(redLight, 1); // Turn on the red lights
                  health = health - (receivedCode.substring(1, 3).toInt()); // Reduce health by incoming damage, if it's an enemy heal it won't have an effect
              }
              else if (receivedCode.substring(1, 3).toInt() == 0)
              {
                Serial.println("heal");
                health = health + healAmount; // Heal if they are a teammate and they are doing 0 damage
              }

          }

          if (health > 100) health = 100; // Set back to 100, cannot be on over 100 health
          else if (health < 1)
          {
              Serial.println ("died");
              switch(receivedCode.substring(0,1).toInt()) // Increment's the killer's kills by one
              {
                case (1):
                  timesKilledByTeam1++;
                  break;
                case (2):
                  timesKilledByTeam2++;
                  break;
                case (3):
                  timesKilledByTeam3++;
                  break;
                case (4):
                  timesKilledByTeam4++;
                  break;
                case (5):
                  timesKilledByTeam5++;
                  break;
                case (6):
                  timesKilledByTeam6++;
                  break;
                case (7):
                  timesKilledByTeam7++;
                  break;
                case (8):
                  timesKilledByTeam8++;
                  break;
              }

              health = 100; // Reset the health
              mag1Ammo = maxAmmo; // Refil the mags
              mag2Ammo = maxAmmo;

              // Update the LCD
              lcd.clear();
              lcd.setCursor(0,0);
              lcd.print("You died!");
              lcd.setCursor(0,1);
              lcd.print("Return to base");

              if (respawn == false) gameDone = true; // If playing one life gamemode, end game
              else // Otherwise wait until respawn code is recieved
              {
                  //irrecv.enableIRIn(); // sending ir stops the receiver so start the receiver again
                  while ((receivedCode != "50") && (gameDuration - (millis() / 1000 - gameStartTime) > 1)) // Keep looking for IR siginal until it's 50 or the time's up
                  {
                      //irrecv.enableIRIn(); // sending ir stops the receiver so start the receiver again
                      if (irrecv.decode(&results)) // if we have received an IR signal
                      {
                          receivedCode = String(results.value, DEC); // Store the received code in received code variable
                          irrecv.resume();
                      }
                  }
              }
              FullDisplayUpdate(teamOrPlayer); // Reset the LCD to gameplay mode

          }
      }
    }

    void setup()
    {
      lcd.begin(16, 2); // Set up the LCD's number of columns and rows
      Serial.begin(9600); // Send code at 9600 bits per second
      irrecv.enableIRIn(); // Start the receiver
      pinMode(trigger, INPUT_PULLUP);
      pinMode(magReader1, INPUT_PULLUP);
      pinMode(magReader2, INPUT_PULLUP);
      pinMode(healButton, INPUT_PULLUP);
    }

    void loop() // Repeat while looking for game (between games)
    {
        Serial.println("\nlp");
        digitalWrite(redLight, 1); // Turn on the lights to show player isn't playing at the moment

        // Print waiting screen to LCD
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("Awaiting start");
        lcd.setCursor(0,1);
        lcd.print("Player: " + String(playerNumber));

        //irrecv.resume();//  NOT YET TESTED
        //irrecv.enableIRIn(); // sending ir stops the receiver so start the receiver again
        while (not irrecv.decode(&results)) // wait until we have received an IR signal
        {
            // Transmit previous game data while we wait
            //Serial.println("wait");
        }

        receivedCode = String(results.value, DEC); // Store the received code in a string variable
        Serial.println(receivedCode); //display results
        irrecv.resume();

        if (receivedCode.length() == 4) // It was a sucessfull transmission if the recieved code was 4 characters long
        {
          playerClass = receivedCode.substring(3, 4).toInt(); // Set the class to the recieved class
          Serial.println("clss: " + String(playerClass));
          SetupClass();

          gameDuration = 180 * (receivedCode.substring(1,2).toInt() + 1); // Set the time remaining and game duration to the received time
          Serial.println("tm lft" + String((gameDuration - (millis() / 1000 - gameStartTime))) + ", gameDuration: " + String(gameDuration));

          // Reset the death counter as a new game is starting
          int timesKilledByTeam1 = 0;
          int timesKilledByTeam2 = 0;
          int timesKilledByTeam3 = 0;
          int timesKilledByTeam4 = 0;
          int timesKilledByTeam5 = 0;
          int timesKilledByTeam6 = 0;
          int timesKilledByTeam7 = 0;
          int timesKilledByTeam8 = 0;

          health = 100;

          switch (receivedCode.substring(0, 1).toInt()) // Do operations based on the received game mode
          {
              case (1): // TDM
                Serial.println("TDM");
                gameMode = 1;
                teamOrPlayer = receivedCode.substring(2, 3).toInt();
                respawn = true;
                Play(); // Call play with received team and respawn on
                break;

              case (2): //FFA
                gameMode = 2;
                Serial.println("FFA");
                respawn = true;
                teamOrPlayer = playerNumber;
                Play(); // Call play with player number and respawn on
                break;

              case (3): // LTS
                gameMode = 3;
                Serial.println("LTS");
                respawn = false;
                teamOrPlayer = receivedCode.substring(2, 3).toInt();
                //Play(); // Call play with received team and respawn off
                break;

              case (4): // LPS
                gameMode = 4;
                Serial.println("LPS");
                respawn = false;
                teamOrPlayer = playerNumber;
                //Play(); // Call play with player numebr and respawn off
                break;

              default:
                Serial.println("Unknown Gamemode");
                break;
          }

        }

    }

// End of code 2

I know this code is a mess, I should not be using global variables and there should be more subroutines, but I wrote most of it before remembering about them :/

If I run the sketch and don't "shoot" on that reset, the code works fully as intended, but the "times killed by player x" variables section I haven't got to yet.

Extra information which I don't think is relevant:

There is a third Arduino which allows you to choose a code and send it, or send the code "50". This is the "base" which someone must return to in order to respawn, as it's the only thing which can send the code "50". The codes it can send are explained below:

It sends a 4-digit number, but it's read as 4 separate numbers, for example, consider the code "rspq". The r is the game mode (1=team respawn, 2=free for all, 3=last team standing, 4=last player standing), s is the duration of the game (time(s) = 3 * (s + 1), resulting in possible times of 3,6,9...30), p is the team that that player is on (when playing a team game)(when not playing a team game it just uses the player ID stored on that particular gun) and q is the class (1=medic, 2=assault, 3=sniper).

There is a lot to say so if you have any questions just ask.

Any help/ideas would be appreciated, thanks in advance.

title: Cannot receive IR codes after sending IR on same Arduino (I have irrecv.enableIRIn();)

Answers: 1

body: It would appear that the audio aspect of my larger program was interfering with the IR receiver, as every time I send IR I also play a sound. It was the sound which was stopping the receiver, not the IR transmitter. When I removed the sound from the sketch, it worked as intended. Thanks timemage for your help.


body:
I'm trying to communicate between two NRF24L01+PA+LNA modules.

I know that NRF24L01+PA+LNA modules are consuming a lot of power and here is my 3.3V power circuit.

[![LM317-based voltage regulator schematic][1]][1]

  [1]: https://i.stack.imgur.com/aELbm.png

The LM317 datasheet says it can output up to 1.5 Amp.
I'm not using Arduino, I'm using STM32F103 blue pill and I'm powering it from this single LM317 linear voltage regulator.

I'm using 1100 mAh, 8.4V LIPO battery, one for Transmitter module(NRF24L01+PA+LNA and STM32 Blue Pill) and second one for receiver module (also with NRF24L01+PA+LNA and STM32 Blue Pill).

**So my problem is that, when I'm TOUCHING the Transmitter's antenna somewhere in the middle with my FINGERS, then it transmits; If I'm not touching the antenna, it does not transmit.**

I also added additional 100uF polar capacitors between NRF24L01+PA+LNA's VCC and GND, but it does not help.

What else can I do?

title: NRF24L01+PA+LNA communication problem

Answers: 0


body:
I have the BLE Module [Adafruit ItsyBitsy nRF52840 Express][1] and I want to send sensor values from a Hallsensor to my computer. I was able to have the right data checking with the Serial monitor.

    int adcin = A1;
    int adcvalue = 0;
    float mv_per_lsb = 1200.0F/4096.0F; // 10-bit ADC with 3.6V input range
    double freq = 100;
    uint32_t lastMicros = 0;  //variable to track sampling frequency
    double microseconds = 1000000.0;
    double interval = microseconds/freq;

    void setup()
    {
      Serial.begin(115200);
      // Set the analog reference to 3.0V (default = 3.6V)
      analogReference(AR_INTERNAL_1_2);
      // Set the resolution to 12-bit (0..4095)
      analogReadResolution(12); // Can be 8, 10, 12 or 14
      // Let the ADC settle
      delay(1);
    }

    void loop() {

      // Get a fresh ADC value after intervall (1/freq)
      if (micros()-lastMicros >= interval)
      {
        adcvalue = analogRead(adcin);
        lastMicros = micros();

        // Display the results
        Serial.print(lastMicros);
        Serial.print(" [");
        Serial.print((float)adcvalue * mv_per_lsb);
        Serial.println(" mV]");
      }
    }

Then I tried to send these values through BLE connectin to my computer. So I knew I had to create a service and a characteristic for the GATT profile. But using the [guide from adafruit][2] was not really helpful. Right know I saw that with the following code I was able to see the module on my computer and read the characteristic I made. But it seems to just give me random Hex values rather than my sensor data.

    #include <bluefruit.h>

    BLEService        myService = BLEService(0x187A);
    BLECharacteristic myChar = BLECharacteristic(0x184D);

    BLEDis bledis;    // DIS (Device Information Service) helper class instance

    int adcin = A1;
    int adcvalue = 0;
    float mv_per_lsb = 1200.0F/4096.0F; // 10-bit ADC with 3.6V input range
    double freq = 100;
    uint32_t lastMicros = 0;  //variable to track sampling frequency
    double microseconds = 1000000.0;
    double interval = microseconds/freq;
    float volt = 0;

    void setup()
    {
      Serial.begin(115200);

      //Setup for data acquisition
      // Set the analog reference to 3.0V (default = 3.6V)
      analogReference(AR_INTERNAL_1_2);
      // Set the resolution to 12-bit (0..4095)
      analogReadResolution(12); // Can be 8, 10, 12 or 14
      // Let the ADC settle
      delay(1);

      Serial.println("BLE data acquisition");
      Serial.println("-----------------------\n");

      // Initialise the Bluefruit module
      Serial.println("Initialise the Bluefruit nRF52 module");
      Bluefruit.begin();

      // Set the advertised device name (keep it short!)
      Serial.println("Setting Device Name to 'Adafruit_BLE'");
      Bluefruit.setName("Adafruit_BLE");

      // Set the connect/disconnect callback handlers
      Bluefruit.Periph.setConnectCallback(connect_callback);
      Bluefruit.Periph.setDisconnectCallback(disconnect_callback);

      // Configure and Start the Device Information Service
      Serial.println("Configuring the Device Information Service");
      bledis.setManufacturer("Adafruit Industries");
      bledis.setModel("Bluefruit");
      bledis.begin();

      // Setup the BLEService and BLECharacteristic classes
      Serial.println("Configuring the custom Service");
      setupSer();

      // Setup the advertising packet(s)
      Serial.println("Setting up the advertising payload(s)");
      startAdv();

      Serial.println("Ready");
      Serial.println("\nAdvertising");
    }

    void startAdv(void)
    {
      // Advertising packet
      Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
      Bluefruit.Advertising.addTxPower();

      // Include custom Service UUID
      Bluefruit.Advertising.addService(myService);

      // Include Name
      Bluefruit.Advertising.addName();

      Bluefruit.Advertising.restartOnDisconnect(true);
      Bluefruit.Advertising.setInterval(32, 244);    // in unit of 0.625 ms
      Bluefruit.Advertising.setFastTimeout(30);      // number of seconds in fast mode
      Bluefruit.Advertising.start(0);                // 0 = Don't stop advertising after n seconds
    }

    void setupSer(void)
    {
      myService.begin();

      myChar.setProperties(CHR_PROPS_READ);
      myChar.setPermission(SECMODE_OPEN, SECMODE_OPEN);
      myChar.setFixedLen(4);
      myChar.begin();
    }

    void connect_callback(uint16_t conn_handle)
    {
      // Get the reference to current connection
      BLEConnection* connection = Bluefruit.Connection(conn_handle);

      char central_name[32] = { 0 };
      connection->getPeerName(central_name, sizeof(central_name));

      Serial.print("Connected to ");
      Serial.println(central_name);
    }

    void disconnect_callback(uint16_t conn_handle, uint8_t reason)
    {
      (void) conn_handle;
      (void) reason;

      Serial.print("Disconnected, reason = 0x"); Serial.println(reason, HEX);
      Serial.println("Advertising!");
    }

    void loop()
    {
      // Get a fresh ADC value after intervall (1/freq)
      if (micros()-lastMicros >= interval)
      {
        adcvalue = analogRead(adcin);
        lastMicros = micros();
        volt = (float)adcvalue * mv_per_lsb;
        // Display the results
        Serial.print(adcvalue);
        Serial.print(" [");
        Serial.print(volt);
        Serial.println(" mV]");
        myChar.write16(volt);
      }
    }

I really got confusing with how to write my sensor values to the characteristic.

Does anyone know how I can achieve that?
Cheers

  [1]: https://www.adafruit.com/product/4481
  [2]: https://learn.adafruit.com/bluefruit-nrf52-feather-learning-guide/blecharacteristic

title: Send sensor data through GATT with Adafruit Bluefruit

Answers: 0


body:
I'm building a simple cnc machine that just writes letters. It uses 2 steppers for x and y axis.

Here is how it works

1. generate letters in c# and convert them to list of lines
2. send to arduino mov_xy line.x line.y as string for each line
3. on arduino convert to int, multiply by steps per mm and run with speedy stepper

It eventually builds up to accuracy problems.
If it's writing "ZWX", letter "X" would be slightly to the side.

Things i tried:
- 500000 baud rate
- accumulate remainder of float number of steps
- different usb cables
- different cnc machines

It is serial communication error?

Do i need to implement CRC?

Can UNO handle this?

Does SERIAL_8E1 do parity check automatically or do i need do something?

I went trough everything many times.
What am i missing here?

[![enter image description here][1]][1]

This image is generated directly from letter lines in c#, so i doubt the problem is on c# side.

  [1]: https://i.stack.imgur.com/UVi12.png

title: 2 stepper cnc inaccurate

Answers: 1

body:
I forgot to take care of negative steps in remainder accumulation.
This solved it.

    // x accum
    float resX = mmX * (float)X_STEPS_PER_MM;
    float lresX = (long)resX;
    _x_acum += resX - lresX;

    long extraStepsX = 0;
    while(_x_acum > 1.0f){
         _x_acum -= 1.0f;
         ++extraStepsX;
    }

    while(_x_acum < -1.0f){
         _x_acum += 1.0f;
        --extraStepsX;
    }
    // move stepper for lresX + extraSteps


body:
Hello programmers out in the world.
I am doing a capstone project for an RF sniffer to capture RF signals from Key fobs within an OEM manufacturing plant. I want to be able to decode this RF signal to show me what the battery state of the key fob is. I have the protocol, so I know what data I should be receiving. However, I have tried many libraries on the Arduino UNO and none have worked.
This Key fob specs are FSK modulation. Frequency of 433 Mhz, Bit rate -> 9.6Kbit/s, baud rate of 19.2Kbaud/s and coding is manchester.

Any help would be greatly appreciated.

[![enter image description here][1]][1]

  [1]: https://i.stack.imgur.com/5oG42.png

title: RF sniffer with Arduino

Answers: 1

body:
I actaully found this this week that I was suing ASK RF receiver module, when I needed FSK.
I have used RC Switch, and no luck, along with Radio head.
However as mentioned the key fob will not work with ASK. I am trying to find a library for FSK but no luck as of now.

-Pete


body:
I am working on a Arduino tachometer that reads the RPM of a BLDC motor. The motor circuit does not use the hall sensors so I would like to use them for RPM sensors. I have already hooked up an Uno board using one pin as an input with the internal pull up enabled and it works fine.The reason I want to use all 3 hall sensors is to increase the pulse count per revolution to steady the reading on my LCD display at lower speeds.
I have been searching for information on how to read 3 inputs, and totalize the pulses for this purpose but have not been able to find the information.

title: How to use 3 digital input pins on Arduino Uno for frequency inputs and total the output?

Answers: 2

body:
Assuming that only one sensor will trigger each time then (as jsotola suggested) tie them together and connect the common output to an interrupt pin. Arduino UNO has interrupt functionality on pins 2, 3.

As an example for counting the pulses using pin2 on falling edge (modified from https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/):

    const byte interruptPin = 2;
    volatile int numPulses = 0; // change type of variable according your needs

    void setup() {
        pinMode(interruptPin, INPUT_PULLUP);
        attachInterrupt(digitalPinToInterrupt(interruptPin), sumPulses, FALLING);
        Serial.begin(9600);
    }

    void loop() {
        Serial.println(numPulses);
        delay(500);
    }

     void sumPulses { // keep the ISR as short as possible
        numPulses++;
     }

body:
An alternative method of frequency determination is to measure period and take the reciprocal. It can be extremely accurate and responsive at very low frequencies, so you don't need to combine multiple sensors just to increase the rate.

Note that you are not limited to measuring a single period; you can count the microseconds in N periods to increase resolution at high frequencies.


body:
I have the following code designed to allow me to control my device from my website using **mqtt broker** while internet is available. I also built in a **local webserver** to control the device in case of internet outage given I'm still connected to the same router my device is connected to.

    #include <ESP8266WiFi.h>
    #include <PubSubClient.h>

    int ledPin = 2;

    const char* ssid = "SSID";
    const char* password = "PASS";
    const char* mqtt_server = "MQTTSERVER";
    const char* mqtt_user = "MQTTUSER";
    const char* mqtt_pass = "MQTTPASS";
    const char* mqtt_topic = "topic";
    String mqttpayload;

    WiFiServer server(80);
    WiFiClient espClient;
    PubSubClient client(espClient);

    void setup() {
      Serial.begin(115200);  pinMode(ledPin, OUTPUT);  digitalWrite(ledPin, LOW);

      WiFi.begin(ssid, password);

      while (WiFi.status() != WL_CONNECTED) { delay(100); Serial.print(".");  }  Serial.println("");

      Serial.print("Connected to WiFi");

      client.setServer(mqtt_server, 1883);    server.begin();
    }

    void loop() {
      client.setCallback(callback);
      reconnect();
      if ( mqttpayload == "OFF" ) {   digitalWrite(ledPin, HIGH); Serial.println("Switced OFF"); }
      if ( mqttpayload == "ON" ) {   digitalWrite(ledPin, LOW);  Serial.println("Switced ON"); }
      mqttpayload = "";

      WiFiClient cclient = server.available();
      if (!cclient) {  return;  }  while(!cclient.available()){  }
      String request = cclient.readStringUntil('\r');  Serial.println(request);  cclient.flush();

      int value = HIGH;
      if (request.indexOf("/LED=ON") != -1)   {
     digitalWrite(ledPin, LOW);    value = LOW;      Serial.println("Publish message: ON");    reconnect(); client.publish(mqtt_topic, "ON", true);
      }
      if (request.indexOf("/LED=OFF") != -1)  {
     digitalWrite(ledPin, HIGH);   value = HIGH;     Serial.println("Publish message: OFF");    reconnect(); client.publish(mqtt_topic, "OFF", true);
      }

      cclient.println("HTTP/1.1 200 OK");
      cclient.println("Content-Type: text/html");
      cclient.println("");
      cclient.println("<!DOCTYPE HTML>");
      cclient.println("");
      cclient.print("LED status: ");

      if(value == HIGH) {    cclient.print("OFF");  } else {    cclient.print("ON");  }
      cclient.println("

");
      cclient.println("Turn ON
");
      cclient.println("Turn OFF
");
      cclient.println("");
      Serial.println("");
    }

    void callback(char* topic, byte* payload, unsigned int length) {
      for (int i = 0; i < length; i++) {     mqttpayload += (char)payload[i]; }
    }

    void reconnect() {
      if (!client.connected()) {
        while (!client.connected()) {
          Serial.print("MQTT..");
          if (client.connect("2021", mqtt_user, mqtt_pass)) {
            Serial.println("MQTT connected");        client.subscribe(mqtt_topic);
          } else { error(); }
        }
      }
      client.loop();
    }

    void error() {  Serial.print("failed, rc=");      Serial.print(client.state());      Serial.println(" try again in 5 seconds");      delay(5000);   }

The problem lies when I test it while connected to my router with **no internet**. The code loops trying to connect to MQTT server and get stuck which doesn't allow me to send local HTTP requests.

I tried modifying the MQTT reconnect loop to the one below, which solves the problem but introduces another issue which is delaying the HTTP requests up to 6-9 seconds.

    void reconnect() {
     if (client.connect("2021", mqtt_user, mqtt_pass)) {
      Serial.println("MQTT connected");
      client.subscribe(mqtt_topic);
     } else { error(); }
     client.loop();
    }

So the question here, **what should I do to get around this issue?**

title: How to avoid MQTT reconnect Loop

Answers: 0