# Question
Title: Arduino Ethernet shield frequently drops its IP address
Im working on a sketch that needs to display some internal variable values and analogue reads in a simple webpage. The only catch is that it *needs* to be as reliable as possible.

Im getting some odd behaviour across multiple shields where the sketch will work briefly (sometimes as long as 5-6 minutes) before cutting out and setting the IP to something weird (commonly 0.0.0.0 or something similar)

My main loop has some other code in it for reading buttons, values, sensors, etc, but the bulk of it is basically

```
void loop()
{
  ... do some stuff ...
  // listen for incoming clients
    EthernetClient client = server.available();
    if (client) {
        Serial.println("new client");
        // an http request ends with a blank line
        boolean currentLineIsBlank = true;
        while (client.connected()) {
            if (client.available()) {
                char c = client.read();
                Serial.write(c);
                // if you've gotten to the end of the line (received a newline
                // character) and the line is blank, the http request has ended,
                // so you can send a reply
                if (c == '\n' && currentLineIsBlank) {
                    // send a standard http response header
                    client.println("HTTP/1.1 200 OK");
                    client.println("Content-Type: text/html");
                    client.println("Connnection: close");
                    client.println();
                    client.println("<!DOCTYPE HTML>");
                    client.println("<html>");
                    // add a meta refresh tag, so the browser pulls again every 5 seconds:
                    client.println("<meta http-equiv=\"refresh\" content=\"5\">");
                    // output the value of each analog input pin
                    client.println(getStrDivByTag("MyWebPage", "h3"));
                    client.println("<br />");

                    client.println("</html>");
                    break;
                }
                if (c == '\n') {
                    // you're starting a new line
                    currentLineIsBlank = true;
                } else if (c != '\r') {
                    // you've gotten a character on the current line
                    currentLineIsBlank = false;
                }
            }
        }
        // give the web browser time to receive the data
        delay(1);
        // close the connection:
        client.stop();
        Serial.println("client disconnected");
    }

  ... do some more stuff ...

}

```

When the server is working as expected, my serial output gives me something like:

> new client
>
> GET / HTTP/1.1
>
> Host: 192.168.1.17
>
> User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86\_64; rv:73.0) Gecko/20100101 Firefox/73.0
>
> Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

But just before it stops working, I get two back to back requests:

> GET / HTTP/1.1 Host: 192.168.1.17 User-Agent: Mozilla/5.0 (X11;
>
> Ubuntu; Linux x86\_64; rv:73.0) Gecko/20100101 Firefox/73.0 Accept:
>
> text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
>
> Accept-Language: en-CA,en-US;q=0.7,en;q=0.3 Accept-Encoding: gzip,
>
> deflate Connection: keep-alive Upgrade-Insecure-Requests: 1
>
> Cache-Control: max-age=0
>
> client disconnected Current Draw: -0.341
>
> 192.168.1.17 new client GET /favicon.ico HTTP/1.1 Host: 192.168.1.17 User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86\_64; rv:73.0)
>
> Gecko/20100101 Firefox/73.0 Accept: image/webp,*/* Accept-Language:
>
> en-CA,en-US;q=0.7,en;q=0.3 Accept-Encoding: gzip, deflate Connection: keep-alive Cache-Control: max-age=0
>
> client disconnected Current Draw: -0.048
>
> 0.0.0.0
>
> Accept-Language: en-CA,en-US;q=0.7,en;q=0.3
>
> Accept-Encoding: gzip, deflate
>
> Connection: keep-alive
>
> Upgrade-Insecure-Requests: 1
>
> Cache-Control: max-age=0
>
> client disconnected

What is that request, something about favicon.ico? After these back to back requests, the IP resets to 0.0.0.0, sometimes jumping to something odd like 0.64.1.0, 0.1.0.64, etc.

Is there an issue with my network configuration, the ethernet2 library Im using?

# Answer
There are many Ethernet sketch examples that are not reliable at all. They basically handle the network setup in setup(), and the TCP connections in loop(). This is wrong. It just means that if there is anything wrong in your network connection, it won't restart correctly. You should check Ethernet.localIP(); and restart your sketch if it doesn't fit. This routine should do the trick : void reset() { asm volatile ("jmp 0"); }

Also, you should be ready for requests for a favicon.ico from usual browsers (that's the small icon that comes in your tabs and favorites) and reply to it (you can use a 404 reply if you don't want to send a file). Providing a robots.txt is also good practice.
> 1 votes

---
Tags: ethernet, networking, ethernet-shield
---


# Question
Title: How can I make the Serial Monitor work with the Serial Commands library?
I am using the library **`SerialCommands`** and I am just trying to print the first text message in the Serial Monitor. But this code does not work for some reason.

The expected result is that the Serial monitor prints a message ("Hello world !!") when I write "hello" and press "enter" as input. Is there something wrong or is this not working like I was expecting? Is there another way to check if these commands work? Is there anythin that I am missing?

```
#include <SerialCommands.h>

char serial_command_buffer_[32];
SerialCommands serial_commands_(&Serial, serial_command_buffer_, sizeof(serial_command_buffer_), "\r\n", ",");

void cmd_hello(SerialCommands* sender) {
  sender->GetSerial()->println("Hello world !!");
}

SerialCommand cmd_hello_("hello", cmd_hello);

void cmd_unrecognized(SerialCommands* sender, const char* cmd) {
  sender->GetSerial()->print("ERROR: Unrecognized command [");
  sender->GetSerial()->print(cmd);
  sender->GetSerial()->println("]");
}

void setup() {
  Serial.begin(9600); // Serial comm begin at 9600bps
  serial_commands_.AddCommand(&cmd_hello_);
  serial_commands_.SetDefaultHandler(&cmd_unrecognized);
  Serial.println("Ready");
}

void loop() {
  serial_commands_.ReadSerial();
}

```

# Answer
You defined, that every command will end with `\r\n`. So you need to choose "Both NL & CR" as line ending in the Serial monitor, so that it appends the line ending to your command. If you don't send the correct line ending, the library will think, that the command hasn't finished yet, and thus will do nothing, until it receives the correct line ending.
> 1 votes

---
Tags: arduino-mega
---


# Question
Title: How to connect MPU6050 with Arduino Uno without using A0-A5 pins?
Connecting MPU6050 with Arduino without using A0-A5 pins.

# Answer
You could use a Software I2C library, like this one on github, which can be used on almost any pin of a board. But keep in mind, that doing such communication in software imposes some limits (for example the linked library can only be a master). Keeping it in hardware is often the better choice, depending on your requirements.
> 1 votes

---
Tags: arduino-uno, mpu6050
---


# Question
Title: Reading sensor with current ouput with Arduino
I am having diffuclt times with this sensor, so I kndliy ask for your help! The sensor is named "SPUVA-CS-C3535-A", datasheet here. The sensor I use (cs3535) has just two pins (+ and -). From my undesrstanding the ouput is a current corresponding on the UV light exposed to this sensor. Max value of the current is difficult to understand from the datasheet that also do not have a typical suggested circuit. It seems that a medium value is 200nA, it seems really low! I have connected (+) of the sensor to 3.3V, (-) of the sensor to A0, and a 220ohm resistor from A0 to Gnd. But readings are always 0. Any help would be really appreciated! Thanks

# Answer
> 0 votes
The "sensor" is just a photodiode that is sensitive to UV. You use it the same as any photodiode.

The simplest (and crudest) way is to use a very large (eg 1MΩ) pullup resistor to 5V on an ADC pin, then connect the sensor (reverse biased) between the ADC pin and GND.

---
Tags: arduino-uno, sensors, current
---


# Question
Title: Controlling VFD with ModBus RTU via RS485 and Arduino
I am attempting to control a Folinn VFD (Manual: Manual) with an Arduino Uno via a MAX485 module such as this.

* Pins for MAX485:
    + DI \> D8
    + DE & RE \> D10
    + RO \> D11

VFD settings:

* F00.01 set to 2
* F00.06 set to 9
* F13.00 set to 1
* F13.01 set to 5
* F13.02 set to 3

At this stage I am attempting a very simple code just to turn the VFD on:

```
/*

   ModBus RTU control VFD

   Address               : 01H  (is the address of the VFD)
   Function              : 06H  (write function code)
   Starting data address : 20H
                         : 00H  (2000H  is the address of control command)
   Data(2Byte)           : 00H
                         : 01H  (0001H is forward command)
   CRC CHK Low           : 43H
   CRC CHK High          : CAH

*/

#include <SoftwareSerial.h>

#define SSerialRX        11  //Serial Receive pin
#define SSerialTX        8  //Serial Transmit pin
#define SSerialTxControl 10   //RS485 Direction control
#define RS485Transmit    HIGH
#define RS485Receive     LOW
#define Pin13LED         13

// From manual vfd Forward command = 01H 06H 2000H 0001H 43CAH

byte request1[] = {0x01, 0x06, 0x20, 0x00, 0x00, 0x01, 0x43, 0xCA};

SoftwareSerial RS485Serial(SSerialRX, SSerialTX); // RX, TX
byte byteSend;

void setup()
{
  // Start the built-in serial port, probably to Serial Monitor
  Serial.begin(9600);
  Serial.println("SerialRemote");  // Can be ignored

  pinMode(Pin13LED, OUTPUT);
  pinMode(SSerialTxControl, OUTPUT);

  // digitalWrite(SSerialTxControl, RS485Receive);  // Init Transceiver

  RS485Serial.begin(9600);

}
void loop()
{
    digitalWrite(SSerialTxControl, RS485Transmit);
    RS485Serial.write(request1, sizeof(request1));

}

```

With the MAX485 connected to the correct ports (S+ and S-) on the VFD, this current setup receives no response is someone able to spot where I am going wrong? I have taken the values for CRC CHK Low & High from a different example, is this the issue?

Have also tried setting F00.01 to an unlisted '3' setting that I have seen pop up in other discussions but this made no difference. Any advice would be much appreciated, let me know if I can supply further details.

(I chose this method based on this example

# Answer
User on other site (https://forum.arduino.cc/index.php?topic=663365.0) Might have default run conditons on VFD set differently or by hardware.

Check the VFD is listening to the ModBus Comms. OK.

Check VFD is 'Ready to Run'. Hardwire e-stop or 'Active' inputs. F00.22 Check Binding source F00.05 Check Set min Hz F01.01 Check Set min Hz

Give drive MIN Hz So when received RUN signal has default speed to goto.

Are you doing a Hard Reset on the UNO every time you want to send the Modbus string? Code runs once, does not actively transmit.
> 1 votes

---
Tags: arduino-uno, serial, rs485, modbus
---


title: LowPower.idle isn't waiting

text:
# Question
Title: LowPower.idle isn't waiting
I am trying to have my Arduino wait in a low power idle state given by the LowPower library made by rocketscream on an Uno. However, when I try to have it wait for 8 seconds, it seems to not pause at all. Does anyone know how to make it so it waits the full 8 seconds before running the next line of code?

Here is the code:

```
#include "LowPower.h"

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

void loop() {
   delay(100);
   Serial.println("above");
   delay(100);

   LowPower.idle(SLEEP_8S, ADC_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_ON, SPI_OFF, USART0_OFF, TWI_OFF);

   delay(100);
   Serial.println("below");
}

```

I would expect this to print "above", then wait 8 seconds, then print "below", then do it again. But what happens is it runs right through the LowPower.idle without doing anything and the output looks like:

> 1:12:14.547 -\> above
>
> 21:12:14.746 -\> below
>
> 21:12:14.845 -\> above
>
> 21:12:15.044 -\> below
>
> 21:12:15.144 -\> above
>
> 21:12:15.376 -\> below

...and so on.

If anyone has any ideas on how to make idle wait, that would be great.

Thanks!

# Answer
> 1 votes
FYI, this issue was brought up nearly 3 years ago, with no response from the author: https://github.com/rocketscream/Low-Power/issues/36

---
Tags: arduino-uno, power
---


# Question
Title: Pass templated function as attachInterrupt parameter
So I want to do something like this:

```
template<int PIN, int CHANNEL>
void initPin() {
    attachInterrupt(PIN, rising<PIN, CHANNEL>, RISING);
}

template<int PIN, int CHANNEL>
void rising() {
    startTimes[CHANNEL] = micros();
    attachInterrupt(PIN, falling<PIN, CHANNEL>, FALLING);
}

template<int PIN, int CHANNEL>
void falling() {
    values[CHANNEL] = micros() - startTimes[CHANNEL];
    attachInterrupt(PIN, rising<PIN, CHANNEL>, RISING);
}

```

but the compiler gives me this error

```
no matches converting function ‘rising’ to type ‘void (*)()’

```

Can I even do this, or do I have to write all the functions by myself?

# Answer
> 1 votes
Try this:

```
template<int PIN, int CHANNEL> void initPin() {
    attachInterrupt(PIN, rising<PIN, CHANNEL>, RISING);
}

template<int PIN, int CHANNEL> void rising() {
    startTimes[CHANNEL] = micros();
    attachInterrupt(PIN, falling<PIN, CHANNEL>, FALLING);
}

template<int PIN, int CHANNEL> void falling() {
    values[CHANNEL] = micros() - startTimes[CHANNEL];
    attachInterrupt(PIN, rising<PIN, CHANNEL>, RISING);
}

```

The problem is actually the Arduino preprocessor. It adds illegal forward declarations if template functions are formated as your original code.

# Answer
> 1 votes
Please have a look implementation https://github.com/Yurik72/SimpleButton

There are implementation how to assign function with arguments to interrupt handler

---
Tags: c++, interrupt
---


title: How to obtain the type of DHT sensor

text:
# Question
Title: How to obtain the type of DHT sensor
I made a simple temperature controller on DHT11. I want it to work with DHT22 as well having the same code.

However, I can’t find a way how to get known what type of sensor is installed. Is there a way?

# Answer
You can use another library for DHT: https://github.com/markruys/arduino-DHT Although, the library is quite old, it works fine and has *auto-detection* feature.
> 3 votes

# Answer
I don't think that is possible.

What you should do is pass the type (DHT11 or DHT12) to the code, store it and change calculations (or functions) accordingly.

If you use a class, you can pass it as argument of the constructor, so the user of the library only need to set it up once (in the constructor where it belongs). Make it an enumeration, copy it into a class variable and all methods inside your class can use the type.

Something like (not checked):

MyDht.hpp:

```
class MyDht
{
public:
    enum EType { DHT11, DHT12 };

    public MyDht(EType type);

private:
    EType _type;
}

```

Dht.cpp:

```
MyDht::MyDht(EType type)
{
    _type = type;
}

```

And you create the class by:

```
MyDht sensor1(MyDht::DHT11);
MyDht sensor2(Mydht::DHT12);

```
> 1 votes

---
Tags: dht22
---


title: Reading DHT22 reboots arduino

text:
# Question
Title: Reading DHT22 reboots arduino
I’ve got a quite weird behavior of DHT library.

I’ve got DHT22 sensor. If it’s signal cable is not connected, reading the sensor causes a problem: Arduino reboots or hangs in unpredictable places.

If I connect the signal cable again, the problem vanishes.

Is this normal behavior or some sort of bug? I think unsuccessful reading affects some part of Memory.

PS. The project is quite big and I can’t share the code here.

It happens that I found an evidence that dht object influences foreign memory. Look at this code:

```
DV("pClock->isInited 3", pClock->isInited); // prints 1
dht1.readHumidity();
DV("pClock->isInited 4", pClock->isInited); // print 0 !!!!
// nothing more can be called between these lines.

// DV is a macro which prints label and value.
// Both objects created before this.

DHT dht1(11, DHT22);
…
dht1.begin();
…
pClock = new ZhClock(); // uses RTC_DS1307
pClock->init(&rtc); // rtc is RTC_DS1307

```

# Answer
This problem is usual if you are in shortage of RAM. Adafruit's libraries wastes lots of memory. You should be very careful to run their stuff if you are in shortage of memory.

I suggest you to try another library which quite old, but uses much lesser memory to read DHT sensor’s data: https://github.com/markruys/arduino-DHT
> 1 votes

---
Tags: adafruit, dht22
---


# Question
Title: how can i conect a lipo charger to a teensy 4.0?
I have the battery charger product https://www.adafruit.com/product/2124 and a teensy 4.0, that I would like to use to power it. what, if any pin would I connect from bat, to the teensy? Its my understanding that the Lion backpack is a voltage regulator, and thats it. it takes Vin, ground, and Vout. I understand the 5v output goes to the 5volt pin of the teensy. the gnd goes to gnd. should Vin go someplace? Or should I leave it off? Please assist.

# Answer
> 1 votes
The output voltage of the charger board is marked with `BAT`. You should connect it to the Vin pin of the Teensy, which then will convert the batteries 3.7-4.2V down to 3.3V.

Of course you need to connect the grounds of the charger board and the Teensy (on the charger board ground is marked with `G`).

The 5V pin on the charger board is no output. The board does not give you 5V. This is actually the pin for the charging voltage, which is 5V. Here it depends on how you want to charge the battery. If you use an external source, you can simply connect it's 5V to the board. If you want to use the USB jack of the Teensy, you can connect the boards 5V to the Teensys 5V. **But:** Be sure to cut the little trace between Vin and VUSB/5V at the back of the Teensy. You don't want to connect the battery voltage with an USB power source.

---
Tags: power, adafruit, battery, teensy, charging
---


# Question
Title: NodeMCU unable to communicate with MFRC522 RFID reader
I am creating a project that will read the RFID card or tag data, store that into a mysql database and display the data via PHP.

I am using NodeMCU, RC522 RFID reader and Ardunio IDE to do that.

Below is my Arduino code. It successfully connects with WiFi (that I can see via serial monitor) but gives no response when I touch the RFID card to the reader.

I can't find the error.

```
/*
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# RFID MFRC522 / RC522 Library : https://github.com/miguelbalboa/rfid #
#                                                                     #
#                 Installation :                                      #
# NodeMCU ESP8266/ESP12E    RFID MFRC522 / RC522                      #
#         D2       <---------->   SDA/SS                              #
#         D5       <---------->   SCK                                 #
#         D7       <---------->   MOSI                                #
#         D6       <---------->   MISO                                #
#         GND      <---------->   GND                                 #
#         D1       <---------->   RST                                 #
#         3V/3V3   <---------->   3.3V                                #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

#include <ESP8266WebServer.h>
#include <ESP8266HTTPClient.h>
#include <SPI.h>
#include <MFRC522.h>

#define SS_PIN D2  //--> SDA / SS is connected to pinout D2
#define RST_PIN D1  //--> RST is connected to pinout D1
MFRC522 mfrc522(SS_PIN, RST_PIN);  //--> Create MFRC522 instance.

#define ON_Board_LED 2  //--> Defining an On Board LED, used for indicators when the process of connecting to a wifi router

//----------------------------------------SSID and Password of your WiFi router-------------------------------------------------------------------------------------------------------------//
const char* ssid = "apiece solution";
const char* password = "apiece@123";
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------//

ESP8266WebServer server(80);  //--> Server on port 80

int readsuccess;
byte readcard[4];
char str[32] = "";
String StrUID;

//-----------------------------------------------------------------------------------------------SETUP--------------------------------------------------------------------------------------//
void setup() {
  Serial.begin(115200); //--> Initialize serial communications with the PC
  SPI.begin();      //--> Init SPI bus
  mfrc522.PCD_Init(); //--> Init MFRC522 card

  delay(500);

  WiFi.begin(ssid, password); //--> Connect to your WiFi router
  Serial.println("hello");

  pinMode(ON_Board_LED,OUTPUT);
  digitalWrite(ON_Board_LED, HIGH); //--> Turn off Led On Board

  //----------------------------------------Wait for connection
  Serial.print("Connecting");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    //----------------------------------------Make the On Board Flashing LED on the process of connecting to the wifi router.
    digitalWrite(ON_Board_LED, LOW);
    delay(250);
    digitalWrite(ON_Board_LED, HIGH);
    delay(250);
  }
  digitalWrite(ON_Board_LED, HIGH); //--> Turn off the On Board LED when it is connected to the wifi router.
  //----------------------------------------If successfully connected to the wifi router, the IP Address that will be visited is displayed in the serial monitor
  Serial.println("");
  Serial.print("Successfully connected to : ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  Serial.println("Please tag a card or keychain to see the UID !");
  Serial.println("");
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------//

//-----------------------------------------------------------------------------------------------LOOP---------------------------------------------------------------------------------------//
void loop() {
  // put your main code here, to run repeatedly
  readsuccess = getid();

  if(readsuccess) {
  digitalWrite(ON_Board_LED, LOW);
    HTTPClient http;    //Declare object of class HTTPClient

    String UIDresultSend, postData;
    UIDresultSend = StrUID;

    //Post Data
    postData = "UIDresult=" + UIDresultSend;

   // http.begin("http://192.168.1.6/NodeMCU_RC522_Mysql/getUID.php");  //Specify request destination
    //http.addHeader("Content-Type", "application/x-www-form-urlencoded"); //Specify content-type header

    int httpCode = http.POST(postData);   //Send the request
    String payload = http.getString();    //Get the response payload

    Serial.println(UIDresultSend);
    Serial.println(httpCode);   //Print HTTP return code
    Serial.println(payload);    //Print request response payload

    http.end();  //Close connection
    delay(1000);
  digitalWrite(ON_Board_LED, HIGH);
  }
  else
  {
    Serial.println("hi");
     delay(1000);
  }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------//

//----------------------------------------Procedure for reading and obtaining a UID from a card or keychain---------------------------------------------------------------------------------//
int getid() {
  if(!mfrc522.PICC_IsNewCardPresent()) {
    return 0;
  }
  if(!mfrc522.PICC_ReadCardSerial()) {
    return 0;
  }

  Serial.print("THE UID OF THE SCANNED CARD IS : ");

  for(int i=0;i<4;i++){
    readcard[i]=mfrc522.uid.uidByte[i]; //storing the UID of the tag in readcard
    array_to_string(readcard, 4, str);
    StrUID = str;
  }
  mfrc522.PICC_HaltA();
  return 1;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------//

//----------------------------------------Procedure to change the result of reading an array UID into a string------------------------------------------------------------------------------//
void array_to_string(byte array[], unsigned int len, char buffer[]) {
    for (unsigned int i = 0; i < len; i++)
    {
        byte nib1 = (array[i] >> 4) & 0x0F;
        byte nib2 = (array[i] >> 0) & 0x0F;
        buffer[i*2+0] = nib1  < 0xA ? '0' + nib1  : 'A' + nib1  - 0xA;
        buffer[i*2+1] = nib2  < 0xA ? '0' + nib2  : 'A' + nib2  - 0xA;
    }
    buffer[len*2] = '\0';
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------//

```

# Answer
your code is OK, I've made a very similar project and... got the same issue. Solution was not in code only in power supply. RFID need very efficient current source and stable voltage. Check the power source, if you used 7805 as linear voltage stabilizer your project will don't work.
> 1 votes

---
Tags: arduino-ide, rfid
---


title: multiple RC522 RFID on arduino yun

text:
# Question
Title: multiple RC522 RFID on arduino yun
I was trying for one month to make multiple **RC522 rfid readers** work together on SPI on an arduino yun, one works fine, but if **I plug 4**, each with a specific slave select, **only one, sometimes 2, sometimes none are working**.

The library i use is `RFID.h` (i think the miguelbalboa one) , but I had the same results with `MFRC522.h` wich have a specific `readUidMultiReader` so I dont think my code is at fault.

Searching for this issue, I found this question wich is basically my issue, as I suspect the readers I bought are not supporting multidrop. These readers dont work either.

I read about solutions using multiplexers for SPI lines, tristate buffers on miso lines and/or diodes but these are workarounds, and there should be a more straightforward solution.

Also I tested with **no resistors** most of the time, but tried putting 10kΩ from all MISO to 3v3, no change, as i really dont understand what their use are, even if I feel they could be mandatory.

---

*I am using a yun for the builtin ethernet, because I tried nanos with ethernet shields and again the shields are ignoring the Slave select and thus not working with spi multidrop, so each time I plugged the shield on nano, even not using it, rfid stopped working.*

# Answer
> 1 votes
Multiple SPI devices on the same bus shouldn't be a problem. I would try the following steps to narrow down the problem:

1. Add Pull-Up resistors to each CS line (10k should be enough)
(The is no need for resistors on the MISO, MOSI or CLK lines since they a push/pull when active)
2. Make sure each CS is set to `HIGH` before you attempt to access the reader
3. Use a simple sketch that only access 1 reader.

* if you could access the first reader -\> change the sketch to use the second one without changing the hardware setup. Continue until you've checked all readers.
    * if you are not able to communicate with one reader, you still have a bug in your hardware setup
4. When the readers work independently, you could start to write your sketch using more than one at a time. (depending on the libraries this could be quite difficult since the lib must support multiple instances, but first we should check the hardware setup)

# Answer
> 0 votes
I suppose that digital output power from yun is insufficient to drive all four readers - so, you need to add some digital buffers to MOSI, SCK, and RST lines.

74LS07 digital buffer:

---
Tags: spi, rfid, resistor
---


title: esp32-cam publish image to mqtt

text:
# Question
Title: esp32-cam publish image to mqtt
I want to publish image capture through ESP32-CAM to MQTT. Have following code :

```
#include "WiFi.h"
#include "esp_camera.h"
#include "esp_timer.h"
#include "img_converters.h"
#include "Arduino.h"
#include "soc/soc.h"           // Disable brownour problems
#include "soc/rtc_cntl_reg.h"  // Disable brownour problems
#include "driver/rtc_io.h"
#include <StringArray.h>

#include <PubSubClient.h>
#include <base64.h>
#include <libb64/cencode.h>

// Replace with your network credentials
const char* ssid = "####";
const char* password = "####";

// Add your MQTT Broker IP address, example:
const char* mqtt_server = "###.cloudmqtt.com";
const int mqtt_port = 11073;
const char* mqtt_user = "###";
const char* mqtt_password = "###";

#define SLEEP_DELAY 10000 //Delay ofr 10 Sec
#define FILE_PHOTO "/photo.jpg"

// OV2640 camera module pins (CAMERA_MODEL_AI_THINKER)
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27
#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22

//#define ESP32_CLIENT_ID = WiFi.macAddress()
//const char* esp_client_id = WiFi.macAddress()
WiFiClient mqttClient;
PubSubClient client(mqttClient);

const int LED_BUILTIN = 4;

void setup_camera() {
      // Turn-off the 'brownout detector'
      WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);

      // OV2640 camera module
      camera_config_t config;
      config.ledc_channel = LEDC_CHANNEL_0;
      config.ledc_timer = LEDC_TIMER_0;
      config.pin_d0 = Y2_GPIO_NUM;
      config.pin_d1 = Y3_GPIO_NUM;
      config.pin_d2 = Y4_GPIO_NUM;
      config.pin_d3 = Y5_GPIO_NUM;
      config.pin_d4 = Y6_GPIO_NUM;
      config.pin_d5 = Y7_GPIO_NUM;
      config.pin_d6 = Y8_GPIO_NUM;
      config.pin_d7 = Y9_GPIO_NUM;
      config.pin_xclk = XCLK_GPIO_NUM;
      config.pin_pclk = PCLK_GPIO_NUM;
      config.pin_vsync = VSYNC_GPIO_NUM;
      config.pin_href = HREF_GPIO_NUM;
      config.pin_sscb_sda = SIOD_GPIO_NUM;
      config.pin_sscb_scl = SIOC_GPIO_NUM;
      config.pin_pwdn = PWDN_GPIO_NUM;
      config.pin_reset = RESET_GPIO_NUM;
      config.xclk_freq_hz = 20000000;
      config.pixel_format = PIXFORMAT_JPEG;

      if (psramFound()) {
        config.frame_size = FRAMESIZE_UXGA;
        config.jpeg_quality = 10;
        config.fb_count = 2;
      } else {
        config.frame_size = FRAMESIZE_SVGA;
        config.jpeg_quality = 12;
        config.fb_count = 1;
      }
      // Camera init
      esp_err_t err = esp_camera_init(&config);
      if (err != ESP_OK) {
        Serial.printf("Camera init failed with error 0x%x", err);
        ESP.restart();
      }
  }

// Capture Photo and Save it to SPIFFS
void capturePhoto( void ) {
  camera_fb_t * fb = NULL; // pointer
  bool ok = 0; // Boolean indicating if the picture has been taken correctly

  // Take a photo with the camera
  Serial.println("Taking a photo...");

  fb = esp_camera_fb_get();
  if (!fb) {
    Serial.println("Camera capture failed");
    return;
  }

  Serial.print("Heap Size : ");
  Serial.println(ESP.getFreeHeap());
  //Serial.println(fb->format);
  Serial.print("fb len : ");
  Serial.println(fb->len);
  Serial.print("base64 encode expected len : ");
  Serial.println(base64_encode_expected_len(fb->len) + 1);
  String base64image = base64::encode(fb->buf, fb->len);
  Serial.print("base64 image : ");
  Serial.println(base64image);
  esp_camera_fb_return(fb);
}

void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

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

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address : ");
  Serial.println(WiFi.localIP());
}

void reconnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("ESP32Client", mqtt_user, mqtt_password)) {
      Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(115200);
  setup_camera();
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
  setup_wifi();
  client.setServer(mqtt_server, mqtt_port);
}

// the loop function runs over and over again forever
void loop() {
  Serial.println("PSRAM found: " + String(psramFound()));
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
  capturePhoto();
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  delay(SLEEP_DELAY);
}

```

This prints following to console

```
Connecting to ####
...
WiFi connected
IP address : 192.168.1.247
PSRAM found: 1
Taking a photo...
Heap Size : 187548
fb len : 135966
base64 encode expected len : 181289
base64 image : -FAIL-

```

**Update Feb 15 :**

I tried following code

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

// the loop function runs over and over again forever
void loop() {
  Serial.println("PSRAM found: " + String(psramFound()));
  Serial.print("Total heap: ");
  Serial.println(ESP.getHeapSize());
  Serial.print("Free heap: ");
  Serial.println(ESP.getFreeHeap());
  Serial.print("Total PSRAM: ");
  Serial.println(ESP.getPsramSize());
  Serial.print("Free PSRAM: ");
  Serial.println(ESP.getFreePsram());
}

```

which printed

```
PSRAM found: 1
Total heap: 378748
Free heap: 352836
Total PSRAM: 4194252
Free PSRAM: 4194252

```

These are the board settings

Board : AI Thinker ESP32 CAM

Latest board package :

I tried wit following board settings as well

**Board** : ESP32 Dev Module
**Upload Speed** : 921600
**CPU Frequency** : 240 MHz
**Flash Frequency** : 80 MHz
**Flash Mode** : QIO
**Flash Size** : 4MB
**Partition Scheme** : Default 4MB with spiffs
**Core Debug Level** : Verbose
**PSRAM** : Enabled

which also gives me following output

```
[D][esp32-hal-psram.c:47] psramInit(): PSRAM enabled

Connecting to ###
[D][WiFiGeneric.cpp:337] _eventCallback(): Event: 0 - WIFI_READY
[D][WiFiGeneric.cpp:337] _eventCallback(): Event: 2 - STA_START
[D][WiFiGeneric.cpp:337] _eventCallback(): Event: 4 - STA_CONNECTED
[D][WiFiGeneric.cpp:337] _eventCallback(): Event: 7 - STA_GOT_IP
[D][WiFiGeneric.cpp:381] _eventCallback(): STA IP: 192.168.1.247, MASK: 255.255.255.0, GW: 192.168.1.1
.
WiFi connected
IP address : 192.168.1.247
PSRAM found: 1
Taking a photo...
Heap Size : 187260
fb len : 101157
base64 encode expected len : 134877
base64 image : -FAIL-

```

From this output it looks like PSRAM is enabled. How can I use it for base64 encoded image ?

Also tried to add `byte* psdRamBuffer = (byte*)ps_malloc(500000);` mentioned at https://thingpulse.com/esp32-how-to-use-psram/ but didn't help.

I have this ESP32-CAM

Update :

I got following working, but it crashes for `framesize_t resolution_ =FRAMESIZE_QXGA;` that's why not able to capture 2 Megapixel picture.

```
#include "WiFi.h"
#include "esp_camera.h"
#include "esp_timer.h"
#include "img_converters.h"
#include "Arduino.h"
#include "soc/soc.h"           // Disable brownour problems
#include "soc/rtc_cntl_reg.h"  // Disable brownour problems
#include "driver/rtc_io.h"
#include "SPIFFS.h"
#include "base64.h"
#include <PubSubClient.h>

// Replace with your network credentials
const char* ssid = "xxxxx";
const char* password = "xxxxx";

// Add your MQTT Broker IP address, example:
const char* mqtt_server = "xxxx.cloudmqtt.com";
const int mqtt_port = 1883;
const char* mqtt_user = "xxxx";
const char* mqtt_password = "xxxxx";

//topic name
const char* mqtt_TopicName = "/devices/esp32/data";

framesize_t resolution_ = FRAMESIZE_QVGA;

//use this delay 1000==1 second
#define SLEEP_DELAY 60000 //Delay ofr 60 Sec
#define FILE_PHOTO "/photo.jpg"

// OV2640 camera module pins (CAMERA_MODEL_AI_THINKER)
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27
#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22

//#define ESP32_CLIENT_ID = WiFi.macAddress()
//const char* esp_client_id = WiFi.macAddress()
WiFiClient mqttClient;
PubSubClient client(mqttClient);

const int LED_BUILTIN = 4;

void setup_camera() {
      // Turn-off the 'brownout detector'
      WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);

      // OV2640 camera module
      camera_config_t config;
      config.ledc_channel = LEDC_CHANNEL_0;
      config.ledc_timer = LEDC_TIMER_0;
      config.pin_d0 = Y2_GPIO_NUM;
      config.pin_d1 = Y3_GPIO_NUM;
      config.pin_d2 = Y4_GPIO_NUM;
      config.pin_d3 = Y5_GPIO_NUM;
      config.pin_d4 = Y6_GPIO_NUM;
      config.pin_d5 = Y7_GPIO_NUM;
      config.pin_d6 = Y8_GPIO_NUM;
      config.pin_d7 = Y9_GPIO_NUM;
      config.pin_xclk = XCLK_GPIO_NUM;
      config.pin_pclk = PCLK_GPIO_NUM;
      config.pin_vsync = VSYNC_GPIO_NUM;
      config.pin_href = HREF_GPIO_NUM;
      config.pin_sscb_sda = SIOD_GPIO_NUM;
      config.pin_sscb_scl = SIOC_GPIO_NUM;
      config.pin_pwdn = PWDN_GPIO_NUM;
      config.pin_reset = RESET_GPIO_NUM;
      config.xclk_freq_hz = 20000000;
      config.pixel_format = PIXFORMAT_JPEG;

      if (psramFound()) {
        config.frame_size = resolution_  ;// FRAMESIZE_UXGA;
        config.jpeg_quality = 10;
        config.fb_count = 1;
      } else {
        config.frame_size = FRAMESIZE_SVGA;
        config.jpeg_quality = 12;
        config.fb_count = 2;
      }
      // Camera init
      esp_err_t err = esp_camera_init(&config);
      if (err != ESP_OK) {
        Serial.printf("Camera init failed with error 0x%x", err);
        ESP.restart();
      }
  }

void publishTelemetryFromFile() {
  File file = SPIFFS.open("/b64image.txt", FILE_READ);
  if (!file) {
    Serial.println("There was an error opening the file for read");
    return;
  } else {
    Serial.println(String(file.size())+ "Byte");

  }

  char* data = (char*)heap_caps_malloc(file.size()+1, MALLOC_CAP_8BIT);
  if (data == NULL)
    Serial.println("Can not malloc memory");

  int i=0;

  //while(file.available()){
  for (i=0;i<file.size();i++){
    data[i] = file.read();

  }

  delay(10);

  //client.publish_P( mqtt_TopicName,"qwertyuiopasdfghjkl;zxcvbnm,", true);
  Serial.print( "Published to MQTT " + String(mqtt_server) + " server.." );
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  boolean Status=client.publish_P( mqtt_TopicName, (const uint8_t*)data, file.size(), true);
  Serial.println(String(Status? "Successfully":"Error") );

  free(data);
  file.close();
}

void capturePhoto( void ) {
   // Retrieve camera framebuffer
  camera_fb_t * fb = NULL;
  uint8_t* _jpg_buf = NULL;
  esp_err_t res = ESP_OK;
  size_t frame_size = 0;
  Serial.print("Capturing Image ..");

  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  fb = esp_camera_fb_get();
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
  if (!fb) {
    Serial.println("Camera capture failed");
    res = ESP_FAIL;
  } else {
    Serial.println("Done!");
    Serial.println(String("Size of the image...")+String(fb->len));

    {

      if(fb->format != PIXFORMAT_JPEG){
        Serial.println("Compressing");
        bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &frame_size);
        esp_camera_fb_return(fb);
        fb = NULL;
        if(!jpeg_converted){
          Serial.println("JPEG compression failed");
          res = ESP_FAIL;
        }
      } else {
        frame_size = fb->len;
        _jpg_buf = fb->buf;
        Serial.print("Size of the base64 encoded image...");

        my_base64_encode(_jpg_buf,fb->len,String("Sat Mar 28 11:47:01 EDT 2020") );
        esp_camera_fb_return(fb);
        publishTelemetryFromFile();

      }
    }
  }
  if (res != ESP_OK) {
 //   ESP_LOGW(TAG, "Camera capture failed with error = %d", err);

    return;
  }

 }

void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

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

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address : ");
  Serial.println(WiFi.localIP());
}

void reconnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("ESP32Client", mqtt_user, mqtt_password)) {
      Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

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

  //byte* psdRamBuffer = (byte*)ps_malloc(500000);
  setup_camera();
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
  setup_wifi();
  client.setServer(mqtt_server, mqtt_port);
   if (!SPIFFS.begin(true)) {
    Serial.println("An Error has occurred while mounting SPIFFS");
    return;
  }
}

// the loop function runs over and over again forever
void loop() {
  Serial.println("PSRAM found: " + String(psramFound()));

  capturePhoto();

  if (!client.connected()) {
    reconnect();
  }

  client.loop();
  delay(SLEEP_DELAY);
}

```

# Answer
> 2 votes
As you can see here, the definition of the return value for `esp_camera_fb_get()` is

```
typedef struct {
    uint8_t * buf;              /*!< Pointer to the pixel data */
    size_t len;                 /*!< Length of the buffer in bytes */
    size_t width;               /*!< Width of the buffer in pixels */
    size_t height;              /*!< Height of the buffer in pixels */
    pixformat_t format;         /*!< Format of the pixel data */
} camera_fb_t;

..
camera_fb_t* esp_camera_fb_get();

..

typedef enum {
    PIXFORMAT_RGB565,    // 2BPP/RGB565
    PIXFORMAT_YUV422,    // 2BPP/YUV422
    PIXFORMAT_GRAYSCALE, // 1BPP/GRAYSCALE
    PIXFORMAT_JPEG,      // JPEG/COMPRESSED
    PIXFORMAT_RGB888,    // 3BPP/RGB888
    PIXFORMAT_RAW,       // RAW
    PIXFORMAT_RGB444,    // 3BP2P/RGB444
    PIXFORMAT_RGB555,    // 3BP2P/RGB555
} pixformat_t;

```

Meaning that `fb->buf` and `bf->len` hold the raw data in the format specified by `pixformat_t`. Aka this is not a "string", these are raw bytes, which you can still base64-encode perfectly fine.

So for the base64 library

```
    static String encode(const uint8_t * data, size_t length);

```

it already accepts the right data type and you can do

```
  fb = esp_camera_fb_get();
  ..
  //will be allocated on the heap. Takes about 4/3 of the input size, so basically it doubles your memory requirements
  String imgDataB64 = base64::encode(fb->buf, fb->len);
  //add to a JSON object wit the metadata width, height and format so that it can be decoded

```

You should output the `fb->format` value to check what format the data is, and add this and the width & height information so that the image may be constructted on the other side. Beware high memory requierements since the base64 encoding basically creates a new buffer to store the base64 representation of it. That may be optimized by writing the framebuffer data into an initially bigger buffer which is then transformed in-place. But that would have to be changed at the image driver level.

# Answer
> 0 votes
If it is still not working for you try below code it's working for me:

```
 int image_buf_size = 4000 * 1000;
 uint8_t *image = (uint8_t *)ps_calloc(image_buf_size, sizeof(char));

 size_t length=fb->len;

 size_t olen;

 Serial.print("length is");

 Serial.println(length);
 int err1= mbedtls_base64_encode(image, image_buf_size, &olen, fb->buf, length);

 Serial.println(err1);

 String img((const __FlashStringHelper*) image);

 Serial.println(img);
 //msg1=img;

```

---
Tags: esp8266, esp32, mqtt, espressif
---


title: Mediatek GPS periodic mode

text:
# Question
Title: Mediatek GPS periodic mode
I'm trying to build a low power GPS datalogger and I am trying to get the Mediatek based GPS module (Quectel L80-R) to run in periodic mode. I've sent the PMTK225 code to the module with various parameters, but it never seems to go into stand by or back up mode. Code below.

```
//Testing that commands sent to the GPS unit work

#include <NeoSWSerial.h>
NeoSWSerial gpsPort(3,2); // pins 3/2

#include <NMEAGPS.h>
NMEAGPS gps;

void setup() {

  // connect at 115200 so we can read the GPS fast enough and echo without   dropping chars
  // also spit it out
  Serial.begin(115200);

  gpsPort.begin( 9600 );
  gps.send_P( &gpsPort, F("PMTK605")); //firmware version
  delay(100);
  //gps.send_P( &gpsPort, F("PMTK314,-1")); //reset to default
  //gps.send_P( &gpsPort, F("PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0") ); // RMC_GGA
  //gps.send_P( &gpsPort, F("PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0") ); // RMC only
  delay( 100 );
  //gps.send_P( &gpsPort, F("PMTK220,200") );  // 5Hz
  //gps.send_P( &gpsPort, F("PMTK220,1000") ); //1hz
  delay( 100 );
  //gps.send_P( &gpsPort, F("PMTK225,0")); // normal mode
  //gps.send_P( &gpsPort, F("PMTK223,1,25,180000,60000")); // ephemeris data receiving
  gps.send_P( &gpsPort, F("PMTK225,2,3000,10000")); //period mode but not working
  //gps.send_P( &gpsPort, F("PMTK161")); //stand by mode
  //gps.send_P( &gpsPort, F("PMTK103")); //cold start
  delay(100);
  gps.send_P( &gpsPort, F("PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0") ); // RMC only

  //gps.send_P( &gpsPort, F("PGCMD,33,0") );   // No antenna status messages needed
  delay( 100 );

  Serial.println("Ready!");
}

void loop() {
  if (gpsPort.available())
    Serial.write( gpsPort.read() );
}

```

# Answer
> 1 votes
Quectel L80-R does NOT have periodic mode, while the L80 does.

---
Tags: gps, sleep
---


title: Level shifting 5V <-> 3.3V

text:
# Question
Title: Level shifting 5V <-> 3.3V
My main goal is to use connect the **HC-SR04** ultrasonic sensor with **ESP8266**.

Problem is, HC-SR04 works with **5V** while the ESP8266 works with **3.3V** In order to solve this, idea would be to use a logical level converter.

I bought some of this 3.3V 5V TTL Bi-directional Logic Level Converter(s) a good while ago, and thought they would fit best for this project.

**Here's my setup**

* 5V from arduino
* 3.3V from digital power supply
* GND connected together
* **Nothing** connected to TX0 (HV side)
* Voltmeter connected to TX1 (LV side), **still getting a 3.3V**

**Here's a closer look at the breadboard connections**

Am I doing something wrong ? Any suggestions would be appreciated !

# Answer
Edit: Forget the post above if you just want to know how your board is working. Your board is a retired Spurkfun product - clone.

Here you can see the schematics and all info about your board:

https://learn.sparkfun.com/tutorials/retired---using-the-logic-level-converter

**Original post**:

The module you got, use the BSS138 MOSFET. The circuit is easy, and how @Majenko said, it has just 2 pullups: See https://electronics.stackexchange.com/questions/367052/replace-bss138-with-ao3400a-in-level-shifter-circuit

But this board is really strange: what means TX0, TX1, RX0, RX1 on the same MOSFET? It is better if you can measure it to be sure how to connect the sensor to the TX.

But there is a better way to solve it: Since you just have 1 input to your ESP, why not use 2 resistors?
5V--- 1k --- 2k --- GND
And connect the ESP input between the 2 resistors? It is even faster, because the MOSFET need up to 20ns to change state.
> 1 votes

# Answer
No, you're not doing anything wrong. Those simple MOSFET level shifters work by having both sides pulled up by resistors to their respective power supplies. When one side gets pulled low by a digital signal that LOW is mirrored to the other side of the MOSFET.

If you connect your TX0 pin to GND you will see the TX1 pin go to 0V.
> 0 votes

# Answer
Check this out: https://learn.sparkfun.com/tutorials/bi-directional-logic-level-converter-hookup-guide/all This article gives a comprehensive explanation about the bi-directional logic level converter and it's connection in a circuit.
> 0 votes

---
Tags: arduino-uno, esp8266, arduino-ide, voltage-level, hc-sr04
---


# Question
Title: Dynamically control the output voltage of a 60V DC input
I am hoping to control a 60V DC input source dynamically using my Arduino so that the output voltage could vary between 0v to 60v. At first i was looking into digital potential meter, however I couldn't find any digital pot that can support 60V DC input voltage. I have came across a few articles with similar situation (but theirs with lower voltage).

Could anyone suggest any solution to my problem? Thanks. Any help is much appreciated.

# Answer
Try ZMPT101B. Easy to use and very cheap

Active Single Phase Voltage Transformer Module AC Output Voltage Sensor for Arduino Mega ZMPT101B 2mA
> -1 votes

---
Tags: arduino-mega, digital, voltage, voltage-divider
---


title: SD card fails to initialize

text:
# Question
Title: SD card fails to initialize
I know this question has be asked before on this site. However it was never really answered. I have an Arduino Uno. I am trying to get it to read a 2 GB SDHC Micro SD card. The problem is, the SD card never intializes. I am not sure if there is something wrong with the wiring (which I think is NOT the issue) or the SD card/shield. I have formatted the SD card, but perhaps I did use the wrong settings to do so. Additionally, this SD card is quite old, probably several years. It can still be managed on my PC however.

I bought the following Micro SD shield off Amazon. It has the pins VCC, GND, MISO, CS, MOSI, and SCK, for which I figured the following:

```
MISO = D0
CS = D1
MOSI = CLK
SCK = D3

```

I have the circuit wired in the following way:

```
SCK to Pin 10 on Arduino
CS to Pin 11 on Arduino
MISO to Pin 12 on Arduino
MOSI to Pin 13 on Arduino
VCC to 3.3V source on Arduino
GND to Arduino Ground

```

The image below is a compilation of the closeup of the shield and my wiring. Not that I am also using Pin 9 in the picture. However this is used for a different portion of the circuit.

The code that I am trying to run comes from the SdFat library. Though the Amazon page says the device can be used without this library, I prefer to have it. I am running the `SdInfo.ino` example located in SdFat/SdFat/examples/SdInfo/. I have changed the coding so that:

```
const uint8_t SD_CHIP_SELECT = 10;

```

I have also tried running the `Basic.ino` example in the TMRpcm library, located at: TMRpcm/examples/basic, but this doesn't work either. Below is the code:

```
#include <SD.h>                      // need to include the SD library
//#define SD_ChipSelectPin 53  //example uses hardware SS pin 53 on Mega2560
#define SD_ChipSelectPin 10  //using digital pin 4 on arduino nano 328, can use other pins
#include <TMRpcm.h>           //  also need to include this library...
#include <SPI.h>

TMRpcm tmrpcm;   // create an object for use in this sketch

void setup(){
  tmrpcm.speakerPin = 9; //5,6,11 or 46 on Mega, 9 on Uno, Nano, etc
  Serial.begin(9600);
  if (!SD.begin(SD_ChipSelectPin)) {  // see if the card is present and can be initialized:
    Serial.println("SD fail");
    return;   // don't do anything more if not
  }
  tmrpcm.play("music"); //the sound file "music" will play each time the arduino powers up, or is reset
}

void loop(){
  if(Serial.available()){
    if(Serial.read() == 'p'){ //send the letter p over the serial monitor to start playback
      tmrpcm.play("music");
    }
  }
}

```

In short. My SD card does not initialize, and I cannot seem to figure out why.

# Answer
> 5 votes
The first thing to try is to use the 'proper' pins for the SPI:

```
SCK to Pin 10 on Arduino ---> Pin 13
CS to Pin 11 on Arduino ---> Pin 10
MISO to Pin 12 on Arduino ---> Pin 12
MOSI to Pin 13 on Arduino ---> Pin 11
VCC to 3.3V source on Arduino
GND to Arduino Ground

```

Try that first and see how you get on.

---

By the way, just thought I'd mention, probably worth just following the Adafruit example word for word as I'm guessing your board is pretty much a good fit for this tutorial:

https://learn.adafruit.com/adafruit-micro-sd-breakout-board-card-tutorial

good luck getting it rockin' ;)

# Answer
> 1 votes
That breakout board includes a 3.3V regulator and level shifter. It should be powered from 5V for proper operation.

Also, as @Andology mentions: *use the correct SPI pins*.

# Answer
> 0 votes
If you have checked everything (wiring, coding your correct pin etc), AND you have already formatted the new card with the correct sd formatter and/or fat32 formatter, and it still does not work; I have found the following worked on some cards: Simply create an empty (0 bytes) file on the new card. Cards that were returning all kinds of funny errors (like they are too small - or simply won't initialize) magically start working !

# Answer
> 0 votes
The solution to this problem, is that you have to let digital Pin 10 as output (for the SD library to work) and put out a logic HIGH by adding “digitalWrite(10,HIGH);”. For Arduino Mega you have to do exactly the same ignore pin 53 completely though the comment asks you to change it to 53.

pinMode(10, OUTPUT); // change this to 53 if you are using arduino mega
digitalWrite(10, HIGH); // Add this line

---
Tags: arduino-uno, shields, sd-card, tmrpcm
---


title: Why does my Arduino 3.3v fluctuate?

text:
# Question
Title: Why does my Arduino 3.3v fluctuate?
For some reason, my 3.3v on my Arduino is fluctuating a lot, and I am not sure why. The multimeter is measuring dc voltage and is connected between GND and 3.3v of an Arduino Mega.

The multimeter works fine. Connecting between 5v and GND gives 5V on multimeter.

# Answer
Arduino output voltages may "fluctuate" a few mV but what you showing us in that gif is really unstable.

What you should be doing is:

1. Disconnect everything from Arduino except the power source
2. measure the voltage again;

Is it stable? the problem was because of pulling too much current that causing voltage drop and instability .

Is it unstable?

3. Try checking with another MM and/or change auto-range to manual.

Is it stable when measuring the voltage with another MM? something was wrong with your previous MM.

Still unstable?

4. Connect the Arduino to a 9V power adapter and disconnect the USB cable.

Measure the voltage again, if it's stable the problem was because of some error in the cable or USB power source.

Voltage is still unstable?

5. change the 3.3V voltage regulator.

It should fix the problem if not report back to do some more in-depth problem solving.
> 1 votes

---
Tags: arduino-mega
---


# Question
Title: How can I set up outputs without using digitalWrite?
Consider the following:

```
#define IN1 9
#define IN2 10

pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);

void LeftMotor(Direction direction) {
  digitalWrite(IN1, direction == Forward ? LOW : HIGH);
  digitalWrite(IN2, direction == Forward ? HIGH : LOW);
}

```

How can I modify the `LeftMotor` method to achieve the same result without using digitalWrite?

# Answer
> 2 votes
Setting ports directly is a great way to learn AVR programming. I might recommend this book Make: Avr Programming.

First you need to set the direction of the port in the Data Direction Register as either input or output. If Input, check its state and handle it. Here is a small example.

```
#define HIGH 1
#define LOW 0

#define  SWI_PIN PORTB0
#define  BUTTON PORTB4

int main (void)
{
    // set the pin directions
    DDRB |=  (1 << SWI_PIN); // output
    DDRB &= ~(1<<PORTB4); //input
    while(true){

      if ((PINB & (1<<BUTTON)) == 0){ // pin is high! Rising edge
          PORTB &= ~(1<<SWI_PIN); // LOW turn off swi_pin
      }else {
          PORTB |= (1<<SWI_PIN); // HIGH  turn on swi_pin
      }

}

```

# Answer
> 6 votes
`digitalWrite()` is just a convenience function to hide away complexity from the user, so that she/he can just use a pin number and a value. This complexity takes some time to execute. If this is too slow for you, you need to go a bit deeper into the rabbit hole and use direct port manipulation:

Inside the microcontroller on the Arduino all the special functions for peripherals and such (digital IO, ADC, Serial(UART), SPI, Timer, ...) are configured via Special Function Registers (SFR). These are specific memory places, that are directly connected to the peripherals. You can configure the whole microcontroller by setting these registers to specific values.

For digital IO you first need to know, that the microcontrollers pins are ordered into groups of max 8 pins. These groups are called Ports. Each available port of the microcontroller gets a character, like PORTB. On the Arduino Nano for example PORTD includes the pins 0 to 7.

For each port we have 3 different SFRs (with the x being the character for the corresponding port), where each bit inside the registers corresponds to one pin:

* `DDRx` controls the direction of the pins. If you set a bit to 1 in there, the corresponding pin is set as output. If you set it to zero, the pin will be an input (which is also called High-Z for high impedance, because a digital input pin has a very high resistance).
* `PORTx` controls the output hardware of the digital pins. If you have set a pin as output (as described above) you can use the corresponding bit in the `PORTx` register to set it's state. If you write a 1 to the bit, the pin will become HIGH (means, the voltage on the pin will go to the same level as Vcc, the supply voltage of the micrcontroller). If you write a zero, the pin will go to LOW (meaning the same level as ground). The `PORTx` register has a different function, when you configured a pin as input. In this case, a 1 will turn on the interal pullup resistor of the pin, which pulls the level of the pin to HIGH, when nothing is pulling it down to ground (like a switch for example). A zero disables the pullup.
* `PINx` reflects the current state of the pins. If you configured the pins as input, this is the voltage level, that currently lies at the corresponding pin (about the actual voltage levels, see below). A 1 at a bit means, that the corresponding pin is HIGH, else it is LOW.

You can read all of this in the datasheet of the used microcontroller. The datasheet is a must read (at least the relevant chapters), if you want to control the microcontroller via its registers. In most microcontrollers these registers are named as above. But some microcontrollers might define other names. The corresponding datasheet will list all the registers with rather detailed descriptions.

Now let's take that knowledge into actual code. Here I assume an Arduino Nano, though you can exchange that for most other microcontrollers.

```
// Configure pin D3 as output
DDRD |= (1 << PD3);
// Configure pin D2 as input
DDRD &= ~(1 << PD2);
// Check, if pin D2 is HIGH
if(PIND & (1 << PD2)){
    // Set pin D3 to HIGH
    PORTD |= (1 << PD3);
} else {
    // Set pin D3 to LOW
    PORTD &= ~(1 << PD3);
}

```

---

**Excourse on bitwise operators:** The code above can only be understood by knowing bitwise operators, which are very important for direct port manipulations. I will break down the operations, that are done there:

* First we have `PD2` and `PD3`. These are defines from the Arduino core. They are set to the index of the bit, that corresponds to the named pin. So `PD2` is defined as 2, `PD3` is defined as 3, `PD0` as 0.
* `1 << PD3`: The `<<` operator does a bitwise left shift, which means all bits of the value on the left are shifted to the left by the amount standing on the right of the operator. We shift the value 1 three digits to the left here. In binary that looks like this:

```
0b00000001 << 3 = 0b00001000

```

That set bit in the result is exactly at the place, where the bits for pin PD3 will be in the Special Function Registers.
* `DDRD |= (1 << PD3)`: This is the same as doing `DDRD = DDRD | (1 << PD3)`, so the `|=` operator is just an abbreviation for it. The bitwise OR operator `|` will unite the bits from both sides. If a bit is set to 1 at either side, the result will also have set this bit to 1. This means, that we can set a bit to 1 with this.
* `~(1 << PD2)`: The tilde `~` takes the inversion of the data. Alike above, the value inside the paranthesis can be written as binary value `0b00000100`. The inversion will flip all bits to the other value: `0b11111011`
* `DDRD &= ~(1 << PD2)`: The abbreviation is similar to the above. The bitwise AND operator `&` will also unite the bits of the values around it, but it will only set the resulting bits to 1, if both of the corresponding bits of the values are also set. Here this results in the third bit (the one for D2) being cleared to zero. All other bits (where you can see a 1 at the right value) are left untouched.
* `PIND & (1 << PD2)`: This is similar to the above, but now we don't have an inversion. We are doing `PIND & 0b00000100` here. All bits of the result will be set to zero, except for the bit for D2. It will only be zero, if the corresponding bit was zero in `PIND`. Thus we have isolated the needed bit by this way.

You can also combine the same operations on a single register. Let's say we want to set both D2 and D3 as output. Then we can either write this as two seperate statements

```
DDRD |= (1 << PD2);
DDRD |= (1 << PD3);

```

or we can combine them into one statement by connecting them with the bitwise OR

```
DDRD |= (1 << PD2) | (1 << PD3);

```

---

The Arduino documentation also provides a site to explain direct port manipulation. Also again you should take the time to look into the datasheet of your used microcontroller. At first it will seems very difficult, but doing these direct port manipulations is a great way of learning how to use the SFRs, and then you can do all sorts of cool stuff with your microcontroller. So it really is worth it. You don't need to read or understand the whole datasheet at once.

---

> How can I modify the LeftMotor method to achieve the same result without using digitalWrite?

After all this text now to the specific question. On the Nano pin 9 and 10 are PB1 and PB2. You used a conditional inside your `digitalWrite()` statement, which I will replace by a complete if statement here. So you can use

```
if(direction == Forward){
    PORTB &= ~(1 << PB1);
    PORTB |= (1 << PB2);
} else {
    PORTB |= (1 << PB1);
    PORTB &= ~(1 << PB2);
}

```

instead of your two `digitalWrite()` statements.

# Answer
> 4 votes
chrisl provided a very good reference answer. Here I am just adding a few bits of information about the pin mapping and the pin electrical states.

## Pin mapping

One of the firs things you need when dealing with direct port access is the mapping between the Arduino pin names and the names of the microcontroller (MCU) pins as given by the manufacturer. For the Arduino Nano the mapping is the following:

```
 Arduino │ MCU
─────────┼─────
   RX0   │ PD0
   TX1   │ PD1
   D2    │ PD2
        ...
   D7    │ PD7
   D8    │ PB0
        ...
   D13   │ PB5
   A0    │ PC0
        ...
   A5    │ PC5

```

where “PD0” means “pin number 0 of port D” and so on. Notice that pins A6 and A7 are not listed here, as they are analog only, with no digital I/O capability.

The information above can be found on the product page of the board, under the “Documentation” tab. Alternatively, an image search for “Arduino \<board name\> pinout” will find some nice schematics like the one below:

## Pin states

This has already been covered by chrisl's answer in the description of the `DDRx` and `PORTx` registers. Below is a summary table showing the four available electrical states of the pins, and how they are selected with the DDR and PORT bits:

```
 DDR │ PORT │ electrical state │ equation
─────┼──────┼──────────────────┼─────────────────
  0  │   0  │  INPUT (high-Z)  │ I = 0
  0  │   1  │  INPUT_PULLUP    │ V = Vcc − Rpu I
  1  │   0  │  OUTPUT LOW      │ V = 0
  1  │   1  │  OUTPUT HIGH     │ V = Vcc

```

The provided equations relate the output voltage (V) and the output current (I) of the pin. Beware that these are just rough approximations, as:

* they neglect the output resistance, which is of the order of 25 Ω
* an input pin can have some (sub-µA) leakage current
* the pullup resistor is not completely linear
* the datasheet only provides weak guaranties, such as a range for the output voltage, conditioned on the output current being low enough.

# Answer
> 1 votes
> How can I set up outputs without using digitalWrite?

So this question is actually about the fastest possible implementation of digitalWrite.

As described in other answers this can be achieved by using direct port manipulation. But there are actually libraries (for instance, https://github.com/mikaelpatel/Arduino-GPIO) that does this in a portable way and avoids some of the errors that can occur. The library is 10-100X faster than the Arduino core digital pin functions.

Pins in a MCU are organized in ports. On the AVR there are a set of 8-bit port registers that hold the current pin setting. To change the value of a pin the CPU has to read the register and change the corresponding bit associated with the pin. This has to be done as an atomic operation, i.e. an interrupt may not occur during the update of the port register.

To allow a very fast update, i.e. one instruction/1-2 clock cycle, the CPU has a set of special instructions. For the AVR there are bit set and clear instructions for the 32 first special registers. On the Arduino Mega some of the pins/ports have higher address special registers and cannot use the special instructions. To make the pin operation atomic explicit interrupt handling must be added.

Other issues with direct port manipulation is portability. Code written using the AVR io handling cannot be used on SAM (e.g. Arduino Due). There is actually even issues when changing between AVR MCUs.

In short, a portable faster implementation of digital pin functions is recommended.

Below is the code written with the GPIO. It is portable and as fast as direct port manipulation.

```
#include "GPIO.h"

GPIO<BOARD::D9> IN1;
GPIO<BOARD::D10> IN2;

IN1.output();
IN2.output();

void LeftMotor(Direction direction) {
  IN1 = (direction == Forward ? LOW : HIGH);
  IN2 = (direction == Forward ? HIGH : LOW);
}

```

or

```
void LeftMotor(Direction direction) {
  IN1 = direction != Forward;
  IN2 = direction == Forward;
}

```

or

```
void LeftMotor(Direction direction) {
  if (direction == Forward) {
    IN1.low();
    IN2.high();
  }
  else {
    IN1.high();
    IN2.low();
  }
}

```

---
Tags: arduino-nano, c, digitalwrite
---


title: Understanding values from an MPU6050

text:
# Question
Title: Understanding values from an MPU6050
I'm trying to understand the values that I'm getting from my MPU6050. I believe that there is a problem with my code. I'm not entirely sure how the code is supposed to look like. There doesn't seem to be very many examples on the MPU6050.

What is wrong?

*After taking a look at the system print I found that the numbers that are written out is the time and not the values of the MPU6050. Why am I getting the zeros and nan for?*

*I also had a library problem thats fixed now.*

I got the code from a site and I've modified it because it didn't run for me.

This is my code:

```
// collect readings
accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

// apply gyro scale from datasheet
gsx = gx/gyroScale;   gsy = gy/gyroScale;   gsz = gz/gyroScale;

// calculate accelerometer angles
ary = -(180/3.141592) * atan(ax / sqrt(square(ay) + square(az)));
arx =  (180/3.141592) * atan(ay / sqrt(square(ax) + square(az)));
arz = (180/3.141592) * atan(sqrt(square(ay) + square(ax)) / az);

// set initial values equal to accel values
if (i == 1) {
grx = arx;
gry = ary;
grz = arz;
}
// integrate to find the gyro angle
else{
grx = grx + (timeStep * gsx);
gry = gry + (timeStep * gsy);
grz = grz + (timeStep * gsz);
}

// apply filter
rx = (0.1 * arx) + (0.9 * grx);
ry = (0.1 * ary) + (0.9 * gry);
rz = (0.1 * arz) + (0.9 * grz);

 Serial.print(ax);   Serial.print("\t");
 Serial.print(ay);   Serial.print("\t");
 Serial.print(az);   Serial.print("\t\t");
 Serial.print(gx);   Serial.print("\t");
 Serial.print(gy);   Serial.print("\t");
 Serial.print(gz);   Serial.print("\t\t");
 Serial.print(arx);   Serial.print("\t");
 Serial.print(ary);   Serial.print("\t");
 Serial.print(arz);   Serial.print("\t\t");
 Serial.print(grx);   Serial.print("\t");
 Serial.print(gry);   Serial.print("\t");
 Serial.print(grz);   Serial.print("\t\t");
 Serial.print(rx);   Serial.print("\t");
 Serial.print(ry);   Serial.print("\t");
 Serial.println(rz);

```

This is the output im getting

```
2   1.00    61.00   0.06000     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan
3   61.00   139.00  0.07800     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan
4   139.00  219.00  0.08000     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan
5   219.00  300.00  0.08100     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan
6   300.00  380.00  0.08000     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan
7   380.00  462.00  0.08200     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan
8   462.00  543.00  0.08100     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan
9   543.00  624.00  0.08100     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan
10  624.00  705.00  0.08100     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan
11  705.00  788.00  0.08300     0   0   0       0   0   0       nan nan nan

```

...

```
41  3223.00 3307.00 0.08400     0   0   0       0   0   0       nan nan nan nan nan nan     nan nan nan
42  3307.00 3392.00 0.08500     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan
43  3392.00 3476.00 0.08400     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan
44  3476.00 3560.00 0.08400     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan
45  3560.00 3645.00 0.08500     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan
46  3645.00 3729.00 0.08400     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan
47  3729.00 3813.00 0.08400     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan
48  3813.00 3897.00 0.08400     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan
49  3897.00 3982.00 0.08500     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan
50  3982.00 4066.00 0.08400     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan
51  4066.00 4150.00 0.08400     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan
52  4150.00 4234.00 0.08400     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan
53  4234.00 4319.00 0.08500     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan
54  4319.00 4403.00 0.08400     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan
55  4403.00 4487.00 0.08400     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan
56  4487.00 4571.00 0.08400     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan
57  4571.00 4656.00 0.08500     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan
58  4656.00 4740.00 0.08400     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan
59  4740.00 4824.00 0.08400     0   0   0       0   0   0       nan nan nan     nan nan nan     nan nan nan

```

# Answer
> 2 votes
I think the best choice for you is to read raw data from the sensor using Wire library.

1. First of all, you have to include the "Wire.h" library:

```
#include "Wire.h"

```
2. Next step is to start the I2C communication by calling the following function in `setup()`

```
Wire.begin();

```
3. Now that the master joined the I2C bus, all you have to do is to set the power mode of the module by setting the register `0x6B` to `0x0`. You can use the following function:

```
int sendCommand(int8_t register_address, int8_t register_value) {
Wire.beginTransmission(mpu_address);
Wire.write(register_address);
Wire.write(register_value);
int statusCommand = Wire.endTransmission(true);
Serial.print("I2C Address: "); Serial.print(mpu_address, HEX);
Serial.print(" Register address: "); Serial.print(register_address, HEX);
Serial.print(" Register value: "); Serial.print(register_value, HEX);
Serial.print(" Status command: "); Serial.println(statusCommand);

return statusCommand;
}

```

Please note that the default I2C address for the MPU6050 is `0x68`. You can use the I2C Scanner to find its address.

To actually set the register `0x6B` to `0x0` you have to call the `sendCommand` like below:

```
sendCommand(0x6B,0x0);

```
4. Request the raw data from the MPU6050. You can check the MPU6050 Register Map for additional information. Accelerometer can be found from `0x3B` to `0x40`, temperature from `0x41` and `0x42`, and finally, the gyro from `0x43` to `0x48`. **IMPORTANT!!!** Every register's value occupy 1 byte (int8\_t), so you have to get the values of two registers (2 bytes) and store them in an int16\_t.

Here is the full code to get the angles from the sensor:

```
#include "Wire.h"

int8_t mpu_address = 0x68;
int sendCommand(int8_t register_address, int8_t register_value) {
  Wire.beginTransmission(mpu_address);
  Wire.write(register_address);
  Wire.write(register_value);
  int statusCommand = Wire.endTransmission(true);
  Serial.print("I2C Address: "); Serial.print(mpu_address, HEX);
  Serial.print(" Register address: "); Serial.print(register_address, HEX);
  Serial.print(" Register value: "); Serial.print(register_value, HEX);
  Serial.print(" Status command: "); Serial.println(statusCommand);

  return statusCommand;
}

void setup() {
  //join the I2C bus
  Wire.begin();
  //start serial communication
  Serial.begin(115200);
  delay(1000);

  /* sendCommand can return 5 possile values:
   * -> 0:success
   * -> 1:data too long to fit in transmit buffer
   * -> 2:received NACK on transmit of address
   * -> 3:received NACK on transmit of data
   * -> 4:other error
   */
  while(sendCommand(0x6B,0x0) != 0){
    delay(1000);
  }

  Serial.println("MPU6050 started");
}

void convertRawDataToAngle(int16_t AcX, int16_t AcY, int16_t AcZ) {
  int minVal = 265; int maxVal = 402;
  int xAng = map(AcX, minVal, maxVal, -90, 90);
  int yAng = map(AcY, minVal, maxVal, -90, 90);
  int zAng = map(AcZ, minVal, maxVal, -90, 90);

  int x = RAD_TO_DEG * (atan2(-yAng, -zAng)+PI);
  int y = RAD_TO_DEG * (atan2(-xAng, -zAng) + PI);
  int z = RAD_TO_DEG * (atan2(-yAng, -xAng)+PI);

  Serial.print("X angle: "); Serial.print(x);
  Serial.print(" Y angle: "); Serial.print(y);
  Serial.print(" Z angle: "); Serial.print(z);
}

void readData(int8_t register_address) {

  int bytesReceived = -1;
  int statusCommand = -1;
  do {
    Wire.beginTransmission(mpu_address);
    Wire.write(register_address);
    statusCommand = Wire.endTransmission(false);
    bytesReceived = Wire.requestFrom(mpu_address, 6, true);
    Serial.print("I2C Address: "); Serial.print(mpu_address, HEX);
    Serial.print(" Register address: "); Serial.print(register_address, HEX);
    Serial.print(" Status command: "); Serial.print(statusCommand);
    Serial.print(" Bytes received: "); Serial.println(bytesReceived);
  } while (statusCommand != 0 && bytesReceived != 6);
  //check if MPU6050 sent all the requested data
  //in total 6 bytes, 2 bytes for each axis
  if (Wire.available() == 6) {
    int16_t AcX = Wire.read() << 8 ;
    AcX |= Wire.read();
    int16_t AcY = Wire.read() << 8 ;
    AcY |= Wire.read();
    int16_t AcZ = Wire.read() << 8 ;
    AcZ |= Wire.read();
    convertRawDataToAngle(AcX, AcY, AcZ);
  }
}
void loop() {
  //put your main code here, to run repeatedly:
  readData(0x3B);
  delay(100);
}

```

# Answer
> 1 votes
The output MPU 6050 does need filtering/processing before you can get any sense from it. I have used the library "MPU6050\_6Axis\_MotionApps20.h" with success, it is located here: MPU6050\_6Axis\_MotionApps20.h

I have written an example here: MPU 6050 for MicroView.

---
Tags: arduino-uno, mpu6050
---


title: How to Set Sensor Data Parameters?

text:
# Question
Title: How to Set Sensor Data Parameters?
Good day! How to set sensor Data parameters?

Like the data only set for example it starts with minimum value of 3 and ends with maximum value of 6 and it will turn on led 1 and if minimum value of 1 and maximum value of 2 turn on led 2 just like that?

My actual code for that:

```
float basa = scale.get_units();
if( basa >= 4 )
{
  digitalWrite(led1, HIGH);
}
else if( basa >= 2 )
{
  digitalWrite(led2, HIGH);
}

```

This code shows that if ever it reaches value of 4 the value of 2 will react also so my question is how set sensor data value like it will only react Value1 - Value2 like that.

thank you

# Answer
> 1 votes
For example:

```
float basa = scale.get_units();

digitalWrite(led1, LOW);
digitalWrite(led2, LOW);

if( basa >= 2 && basa < 4 )
{
  digitalWrite(led2, HIGH);
}

if( basa >= 4 )
{
  digitalWrite(led1, HIGH);
}

```

**EDIT: as suggested by @chrisl (see comments)**

If understand you problem correctly, you try to light up 2 LEDs according to the value you read from a scale. IMHO you want to assign three intervals (ranges) like so:

```
(-INF, 2) : none of the LEDs is switched on
[2, 4)    : only LED 2 is switched on
[4, +INF) : only LED 1 is switched on

```
* `[x` or `x]` means the x belongs to the interval.
* `(x` or `x)` means the x does not belong to the interval.
* `+INF` and `-INF` are the positive or negative infinity.

My code does the following:

I use the observation, that the intervals do not intersect and the union of the intervals are the complete real number space. (Although your scale has a more narrow range: (0-?kg). The program can handle a wider range compared to the the scale, so it is not a problem.)

If the first condition `(-INF, 2)` is `true`, none of the others would be and we can be sure that the LEDs I switched off with the `digitalWrite(ledX, LOW);` statements will stay off. If the value is in the range of `[2, 4)` I switch on LED2 and can be sure that the other LED stays off because the condition `basa >= 4` can not be `true`. And if the value is in the range of `[4, +INF)` I switch on LED1 and can be sure that LED 2 has not been switched on because the condition `basa >= 2 && basa < 4` can not be `true`.

---
Tags: sensors, data, constants
---


# Question
Title: Serial communication problem with sim7600 with Arduino Mega
I am just sending the AT command to test if the serial communication works, the response I am getting is a flipped "?" or a square or rectangle symbol.

I have tested the communication using software provided by Waveshare connected through on board USB to UART.

https://www.waveshare.com/wiki/SIM7600E-H\_4G\_HAT

```
int PowerKey = 2;
char answer;

void setup()
{
 Serial3.begin(96u00);
 Serial.begin(9600);
 pinMode(PowerKey, OUTPUT);
 Serial.println("initializing");
 digitalWrite(PowerKey, HIGH);
 delay(1000);
 digitalWrite(PowerKey, LOW);
}

void loop()
{
  answer = send_at_cmd("AT\r\n");
  Serial.println(answer);
}

uint8_t send_at_cmd(const char* ATcommand)
{
  char response;
  // send test command AT
  Serial3.print(ATcommand);
  Serial.println(ATcommand);
  delay(1000);
  //Check for response from the sim7600E-H
  while(Serial3.available() != 0)
  {
    response = Serial3.read();
  }
  return response;
}

```

# Answer
> 0 votes
You have change baud rate by at+iprex=9600 before upload your code, because sim7600 set 115200 by default then save your setting by at&w.

hope this help someone.

---
Tags: serial, arduino-mega
---


title: Sound sensor signals with time bracket

text:
# Question
Title: Sound sensor signals with time bracket
I've tried many codes for this to work but anything isn't helping at all, so my code should work like this: If a sound sensor (3 pins, A2) sends 5 signals into the Arduino within 10 seconds (the time gap of every signal varies, but doesn't matter as long as it sends 5 signals), the LED (13) will light up. This is my recent code if it could help

```
int led=13;
int sensor=A2;

void setup()
{
   pinMode(led, OUTPUT);
    pinMode(sensor, INPUT);
    Serial.begin(9600);
}

void loop()
{
    unsigned long StartMillis = millis();
    unsigned long CurrentMillis = millis();
    int signal_count=digitalRead(sensor);
    int signal_limit=5;
    Serial.println(signal_count);

    while ((CurrentMillis - StartMillis)==5000)
    if (digitalRead(sensor)=0)
    {     signal_count ++;
        Serial.println(signal_count);
    }
    if (signal_count>signal_limit) {
        digitalWrite(led, HIGH);
    }
    else {
    digitalWrite(led,LOW);
    }
}

```

# Answer
> 1 votes
Your handling of `millis()` is wrong. With these two lines:

```
unsigned long StartMillis = millis();
unsigned long CurrentMillis = millis();

```

`StartMillis` will always have the same value as `CurrentMillis`. (Ok, I guess its possible for `millis()` to return a value that's increased by 1 the second time it's called, but that is **extremely** unlikely. The 2 lines takes much less than a millisecond to execute.)

Your

```
while ((CurrentMillis - StartMillis)==5000)

```

will never evaluate to true, so the code in the while block will never execute.

This `if` statement is also wrong:

```
if (digitalRead(sensor)=0)

```

You want `==` (comparison) not `=` assignment. I'm surprised the compiler even allowed that to compile, since you are trying to set the function `digitalRead(sensor)` to 0, which doesn't make sense.

Change that code to read:

```
if (digitalRead(sensor)==0)

```

(Assuming you want the body of the if statement to execute when your sensor value is 0.)

---
Tags: arduino-uno, sensors
---


title: Moving an object in an area

text:
# Question
Title: Moving an object in an area
I am planning to build a little game and I would need to move a small magnet inside a rectangular area. Ideally I would be able to control movement arbitrarily e.g. using a joystick. I am trying to find a way of doing this, something like an actuator, I guess, but allowing movement in 2D. Any suggestions on which parts to use?

Edit : in brief, what I'm trying to do is this. I have a piece of plywood, underneath which I want to put a magnet. The magnet will be moveable using a joystick (everything controlled through an Arduino) and will be used to move a magnetised figurine on the other side of the plywood. I guess in term of precision of movement I am not looking for extreme precision, having something accurate to 2-3mm would be absolutely fine. Haven't really thought of speed... But not looking for extreme high speeds.

# Answer
> 1 votes
First you need to think about your axes configuration, then about the actual implementation. I for example can directly think of 2 options:

* You could arrange your axes perpendicular to each other, like a Cartesian coordinate system. Here you might need more parts to build it, than with other arrangements, though it is a sturdy system and the positions and paths are easily to calculate. For implementation there are 2 common ways, both using stepper motors in most cases:

+ You could let the magnet travel on the 2 perpendicular axes pulled by a belt and stepper motor for each axis. As you have to mount one axes onto the other, you might need to use 2 stepper motors (one for each side) for the first axis (depending on your dimensions, how smooth the axes glide and how much force is introduced by dragging the figurine). This approach is mostly used by 3D Printers, since they need rather fast movement, which is also rather precise, but don't need to accommodate high forces.
    + Instead of belts and pulleys you could use threaded rods for each axis. The magnet is mounted on nuts on these rods. Rotating the rots will move the magnet over the axis, since the magnet is fixed in it's orientation. The precision is highly dependent on the used rods, but all in all it is often more precise, than belts. But it is also way slower.
* You could use only rotational axes, like a SCARA robot. It has a rod on a rotational axis and another axis at the end of it. This approach might use less parts, than the Cartesian approach, but you need good servos to have precise and jitter-free positioning (though you could also go for a geared stepper motor here). Also the arm of the robot can look out under the field quite a bit, when positioning it to the far one side.

---

All of the above approaches can be way more precise, than you need it. They are all viable options.

I personally would go the first way, Cartesian axes with belts and pulleys. The principle is straight forward and you can easily hide it under your piece of plywood (including a margin for all the mechanical stuff of course).

---
Tags: motor
---