text:
ESP8266, prints ready at start but no response to AT command
I have been using ESP8266 wifi module with Arduino as FTDI. The power for ESP8266 comes from LM317 5V - 3.3v regulated supply(I am sure 5V is powerful enough to give upto 1A of current).
The RX of ESP8266 is connected to RX of Arduino via a voltage divider to ensure 3.3V logic level. But still, I am not getting any response to AT command, though my laptop and phone wifi have successfully connected to AI-Thinker... SSID(which is an open hotspot from ESP8266).
I am also having some garbage values on the serial port immediately after I turn on the power supply to ESP8266. I have tested all baud rates available in Arduino IDE v1.0.5 with no results.
The resistor values for lm317 are R1 = 125 Ohm, R2 = 225 Ohm with which I am getting around 3.2 Volts.
The connections are as follows:-

-----Arduino UNO-----
RESET ------------ GND

Arduino UNO ----- ESP8266
TX ------------------- TX
RX ---5V to 3.3v--- RX
GND ----------------- GND

ESP8266 --------- LM317(5V to 3.3V)
VCC --------------- 3.3V
GND --------------- GND
CH_PD ------------ 3.3V

EDIT - 1: I have bought a new ESP8266, and even it doesn't responds to any AT commands, thought there is some difference in the previous ESP8266 output and this new ESP8266 output.
The difference is a sort of good news to me, it sends ready after sending some garbage at 115200 baud on boot which never happened with previous one(ESP8266).
Is anyone having some clue why there is no response to AT commands?
May it be a issue with TX line?

EDIT - 2: I have also used another Arduino with same connections doubting the TX pin on Arduino, but with same luck, bad luck. Still, nothing got changed.

EDIT - 3: I am shifting 5v to 3.3v by using three 100 ohm resistors.

Comments are not for extended discussion; this conversation has been moved to chat.

I think, the blue led should blink even at wrong bauds. Correct me If I am wrong.

blue led blinks only when sending some data, not receiving.

The problem was with my logic level shifting.
Any Arduino pin can provide only upto 40mA of current. What current you are trying to draw is:-

5 Volts / 100 Ohm = 50mA

which is clearly more current than what an UNO can provide. Your ESP also adds up its own resistance meaning even more current draw requirement from RX pin.
Instead of using three 100 ohm resistors, use some high valued resistors such as 1K ohm resistors(or even higher value) in the voltage divider circuit so that no much current pass through it, consuming less power affordable by the Arduino RX pin.
Remark: If you don't know how logic level shifting works with voltage divider circuit, click here.

Connect TX of arduino to esp8266 RX, and arduino RX to esp8266 TX.
See this link for more info.

Comments are not for extended discussion; this conversation has been moved to chat.

The rather extensive set of comments (now moved to chat) should be added to the answer, if indeed they help answer the question. This is not a forum-type situation here on Stack Exchange.

First of all your connectons are wrong:
-----Arduino UNO-----
RESET ------------ GND (Why)
Arduino UNO ----- ESP8266
TX ------------------- RX
RX ------------------- TX
(RX is the recieving end, TX is the transmitting end, one should allways connect a transmitter to a reciever both directions, never a transmitter to transmitter or reciever to reciever, and use a logic level shifter)
GND ----------------- GND
ESP8266 --------- LM317(5V to 3.3V) (only for Vcc)
VCC --------------- 3.3V
GND --------------- GND
CH_PD ------------ 3.3V
In these cases you should use a logic level shifter like 74LVC245 or sparkfun level converter and not a voltage regulator. If you must use lm317 connect it correctly, diodes, capacitors and an adjusting potmeter or resistor. Typical application found in the datasheet on p. 10
baudrate should be 57600 on the esp8266.
glhf :)

When we are doing TX-RX, RX-TX, we are trying to communicate between Arduino MCU and ESP8266, that's why these pins are labelled so. But, in case, we are bypassing the Arduino MCU, we do it this way TX-TX, RX-RX. By bypassing Arduino MCU, our TX and RX on arduino gets reversed i.e. they become RX and TX of computer(if we attach a computer with USB cable)with which we can communicate between a computer and ESP8266 bypassing Arduino

Second thing, I think the ESP8266 is getting enough power as it is showing as wifi hotspot in my laptop and phone as well as sending some bits and then ready in serial console, so maybe nothing to do with LM317, i think.

Third thing, Arduino: RESET --- GND because that's a way to bypass Arduino MCU, we could have done physically removing its ATMEGA328p from the board but that's not a elegant way of doing this.

Which version of arduino IDE are you using? I use 1.6.12 and works, it does not work for 1.8 versions.
Also ensure 3.3v power input for the esp8266 separately from arduino power. I suggest using a PC power supply (color orange is 3.3v).

The issue you are running into is that the Arduino Uno cannot source enough current at 3.3V for esp8266 operation. I had to use a separate power supply with grounds tied together and then my esp8266 responded to AT commands.
Summary:

I use the Arduino Uno as the serial bridge (RESET tied to GND)

an external power supply for the esp8266

and a bidirectional level shifter for 3.3V to 5V TX/RX data paths

Connected CHPD of esp8266 to GND, waited 5 sec then reconnected to 3.4V

Arduino IDE > Tools> Serial Monitor > Both NL&CR > 115200 Baud Rate

and I just connect the Uno to esp-01 directly and it works. but it depends on version of Uno. original Rev 3 gives 150 mA on 3.3 V pins, which is enough for esp-01. there is no need to level shift 3.3 to 5 V and the esp8266 has no problem with 5 V logic level with almost no current flow

@Juraj I’ve read in multiple locations the ESP8266 operating voltage is 3.3V. Also, I level shift because the TX/RX of the Arduino Uno expects 5V whereas the ESP8266 expects 3.3V
https://cdn-shop.adafruit.com/product-files/2471/0A-ESP8266__Datasheet__EN_v4.3.pdf

First of all do not use any resistors(try it) for RX pin. Connect it directly.
Second connect RST pin of ESP8266 to 3.3V power supply.
And also try to use arduino directly with esp8266 once. Do not use lm317 or any other separate power supply. Use 3.3 volt power supply of arduino.
And i dont know why you have connected RESET pin of Arduino to GND. Please answer me that.

I have already tried to connect arduino RX to ESP8266 RX without resistors(voltage divider circuit), but it didn't worked either.
Second, I have not tried RST pin of ESP8266 to 3.3V, I am going to try it now and report back soon.

I also used arduino directly without lm317, it does not shows any hotspot until an external power supply to Arduino is given. I gave arduino 5V external supply, and the hotspot showed again, but this time also, no response to AT command, but garbage on starting.

why are you making things complicated. Connect 3.3V of arduino to esp8266 Vcc port. And you obviously have to provide external power supply to arduino. Connect it to PC using USB Cable. And Connect RST pin to 3.3V.  Use a breadboard.

I have used 3.3V of arduino to esp8266 directly. Given, external power supply to arduino, connected arduino to pc and connected RST pin of ESP8266 to 3.3V. I am still geting garbage at serial on starting and no AT response.

@SONIAJOHNSON You need to power the ESP8266 separately from the Arduino - it required a higher current than the Arduino 3V3 pin is capable of supplying. Also, ESP8266 RX pin does seem to be voltage sensitive, requiring a voltage divider or converter to reduce voltage to 3V3.


text:
rs485 and serial ISP
I made a couple of arduino mini pro and esp8266 pcbs with an rs485 transceiver just to find out that I forgot to think about in-system-programming:
Assuming that I don't need to disable the transceiver i tied *RE/DE to gnd/vcc. It turned out that id do need disable the transceiver (at least the receiving part) in order to be able to program the mcu because otherwise the transceiver disrupts the serial data.
But I don't want to lose one pin for this (which in case of an esp8266 are rare) and I don't want to use jumpers because I really like the workflow without.
Is this even possible?
EDIT: The transceiver is an SP3485.
Currently it is connected like:
Mini Pro     SP3485
A-rx ------  RO
GND  --1k-- *RE   A  ---- somwhere else
Vcc  --1k--  DE   B  ----        "
A-tx ------  DI

Which blocks serial programming because of a) the "echo" and b) holding A-rx line high.
If I connect *RE --1k-- Vcc and DE --1k-- GND I can ISP the Arduino, but now I obviously can't use the transceiver anymore.

I'm not sure why you used an RS-485 transceiver if you were only going to permanently enable the two halves? You've basically turned the RS-485 multi-drop into an RS-422 balanced pair-of-pairs. Ah well!
So you wired the transceiver to TX and RX on the ESP8266? And you want to still use those pins to reprogram it, by going "behind" the transceiver and temporarily connect them to your FTDI/whatever? Yeah, sorry: that's not going to work.
The *RE pin and DE pin only affect the balanced side of the transceiver. The RX and TX pins on the logic side are still an output and input respectively, regardless of the state of the two Enable pins.
That means that to reprogram, you're going to have to connect your development machine to the balanced side of the transceiver, and you won't have to worry about the Enable pins. Look for RS-422 USB cable adapters - they're out there!

Hi John, thanks for your answer. Perhaps my question is not worded so well. I've got one transceiver like the sp3485. So on the balanced side I don't have rx/tx anymore. Only A/B. Connecting on that side will definitely not work. If I disable the transceiver the hard way (connect DE/*RE to gnd/vcc via 1k) I'm able to programm the mini. What I'm looking for is some magic (which I can't think of) which does this for me while programming.

I can't understand the purpose of connecting *RE/DE to GND/Vcc. With
this setup, the driver inside the transceiver is always enabled, and
it's always driving the A/B pair. Meaning the device at the other end of
the link cannot drive the pair itself without making a collision.
Basically you have a simplex link, where the Pro Mini is always the
sender.
The normal way to connect an RS-485 transceiver is to have DE driven by
a GPIO pin of the MCU. You pull this pin HIGH when you want to talk, and
leave it LOW the rest of the time so you can hear other devices talking.
The *RE pin is connected either to GND (if you want to hear the echo of
what you say) or to DE (if you don't).
That being said, you are correct in that the transceiver may cause
problems when uploading the firmware on the Pro Mini. One possible
solution is to put a resistor between RO and A-RX. The TX of the FTDI
cable should have a low output impedance and be able to overpower that
resistor. Another option is to use ICSP (in-circuit serial programming)
instead of going through the bootloader. It would be easier if you can
put an ICSP header on your board.

Hi Edgar. Thanks for your answer. Above all for pointing out the working of the transceiver. Now I understand what John was trying to tell me :) I think I misunderstood it because I have been working with can transceivers which have dominant / recessive state and I somehow implied that this is so for rs485, too, and re/de only have the purpose of enable. Interestingly enough I have alredy built some usb/rs485 transceivers which I did wire in this way and they did work ...

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/

sort: votes


text:
Can't assign elements to index in array
I'm trying to create an array of strings. I'm building each individual string by parsing a json file and getting the strings between '{'s and '}'s. However, for some reason, my array is only assigning one index with the string i want. This is my code:
  String day = "";
  String Combo[] = {"0","0","0","0","0","0","0","0"};
  int x = 2;
  int number = 0;

  /* Read data until either the connection is closed, or the idle timeout is reached. */
  unsigned long lastRead = millis();
  while (www.connected() && (millis() - lastRead < IDLE_TIMEOUT_MS)) {
    /* Reads one character at a time*/
    while (www.available()) {
      char sym = www.read();

      if (sym == '{') {
        x = 1;
      }
      if (x==1){
        if (!day.concat(sym)) {
          //Serial.println("concat() error!");
        }
      }
      if (x==1 && sym == '}'){
        x=0;
        Serial.println(number);
      }

      if ((number > 0) && (number < 9) && (x==0)) {
        Combo[number-1] = day;
        Serial.print(day);
        Combo[number-1] = day;

        Serial.println(F("-------------------------------------"));
        Serial.println(Combo[number-1]);

        Serial.println(F("-------------------------------------"));
        Serial.println(F("-------------------------------------"));
        day = "";
        number +=1;
        x = 2;
      } else if (number ==0 && x ==0){
        day = "";
        number +=1;
        x = 2;
      }
      lastRead = millis();

    }

  }

Which returns this:
{
    "firstString"
    }-------------------------------------

-------------------------------------
-------------------------------------
{
    "secondString"
    }-------------------------------------
{
    "secondString"
    }
-------------------------------------
-------------------------------------
{
    "thirdString"
    }-------------------------------------

-------------------------------------
-------------------------------------
{
    "fourthString"
    }-------------------------------------

-------------------------------------
-------------------------------------
{
    "fifthString"
    }-------------------------------------

-------------------------------------
-------------------------------------
{
    "sixthString"
    }-------------------------------------

-------------------------------------
-------------------------------------
{
    "seventhString"
    }-------------------------------------

-------------------------------------
-------------------------------------
{
    "eighthString"
    }-------------------------------------

-------------------------------------
-------------------------------------
{
    "secondString"
    }-------------------------------------

Based on this output I know that day is being constructed correctly but for some reason isn't assigned to an index in Combo (except "secondString")
Does anyone know what's going on?
Ideally Combo would equal: {"secondString", "thirdString", ... "eighthString"}

Any chance you could show us the JSON file you are trying to parse?

Perhaps you are out of memory?

I'm trying to understand your code.

It looks like x is a state variable, with the following values:
2 = "Looking for start brace (`{`)"
1 = "Found! Now accumulating `day` until stop brace (`}`)"
0 = "Finished!"

If so, you may instead want to use the following:
enum States { Looking, Adding, Done };

// int x = 2;
States state = Looking;

// x = 1
state = Adding;

// if (x==1){
if (state==Adding) {

If you follow the flow of code, when number is still 0 and x finally becomes 0, you:

Print out number - the first line of your output;
You then miss the main if (number is not greater than 0);
And enter the else (which is satisfied);
And then you immediately clear your hard-earned day.

The second time through, after x becomes 0 again, this time you:

Print out number - the second line of your ouptut;
You do enter the main if:

You assign day to Combo[1]
You print out only the first seven entries in the the array (you want <=7, not <7)

This should print out 0{?}000000 (I don't know what day should be).
The fact that it doesn't seems to imply that your concat() failed. Can you please change it to
// day.concat(sym);
if (!day.concat(sym)) {
    Serial.println("concat() error!");
} // if

You then print out the row of dashes - and start a new line.

The third time through, it seems to work - you get your {$ "first string" $} (where $ represents \n and/or \r - can you strip those out?)
      // if (x==1){
      //    day.concat(sym);
      if (x==1 && sym>=' '){ // Don't concat new line characters!
          day.concat(sym);

And the final few times concat() seems to have failed again.

The reason I say "concat() has failed" is that it looks like day is still "" when it is assigned to Combo
Edit
You've changed the code so that the main if now does the following:

Assigns day to Combo[number-1];
Prints out day - this seems to work;
Assigns day to Combo[number-1] again;
Prints out a line of hyphens - this works;
Prints out Combo[number-1] - this does NOT seem to work;
Prints out two lines of hyphens - this works.

Since 5 is printing out nothing, it implies that 3 failed. This really does look like you're in a low-memory condition, and the system is failing to allocate memory from the heap.
You don't say what Arduino you're working on - note that most don't have much memory, and if you're already parsing a JSON file you've probably used a lot of it. You also don't say which version of the Arduino IDE you're using. There was a String bug in the earlier versions.
Rather than trying to use the String class (a renowned heap hogger), you should try to use normal char arrays and work the buffer management yourself.

Thx for the advice. For #2, I don't want the first day string to be saved so that's normal. I implemented #3 and it does seem that my concat fails often. Do you have any advice on fixing this?

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/


text:
Worldwide "Arduino in education" events
I'd like to know if there are events worldwide or in Latin America regarding how to introduce Arduino as an extra-curricular activity.
Thanks, Marcelo from Argentina.


text:
Does sharing code on Arduino Create automatically grant any license rights?
I have code I am happy to share under a GNU GPL License and which is marked accordingly. Before I upload it to Arduino Create Web Editor I want to check whether in doing so I inadvertently grant additional license rights. I have searched for any terms and conditions which may inform me but not found any as yet.

Arduino Create doesn't assume any licensing of any form. Sharing isn't a public thing. You have to specifically provide someone with a link to your sketch. If you choose to post that link publicly then that is your concern.
Any licensing should be included with your sketch.

You should read the GPL License terms with respect to any rights you are concerned about, but in general, GPL licensed software is available to anyone to do anything with, as long as they keep it public and perpetuate the GPL License. Note: IANALawyer. If you wish to protect any specific rights, you should probably consult one.


text:
Requesting help with CNC Project using Arduino
I have made a setup with Arduino Uno, Nema 17, T8 lead screw, IR Sensor and a DC motor.
I am trying to establish a code which:

Resets Home position of the Machining Head on the lead screw
Has an action button, which operates only when the position of the Head is on the lead screw, goes down the specified depth
Takes input from user to run the DC Motor (to rotate the tool on the machine head)
Takes second input to stop rotating and return to the reset position.

I am facing one major problem and two minor problems:
Major Problem:
To remove an error which was later resolved, I added the line: action_permit=0
Now due to some reason (I have pulled a lot of hairs trying to understand this), when I remove this action_permit line, the DC Motor rotation is stopped. I  have to include this line to rotate my DC Motor.
Minor Problem:
To get input from the user as to control when the DC motor starts and stops, I included the code which accepts 'y' for yes (start rotating the DC motor) and 'n' as no (stop rotation and return to home position)
Minor Problem:
I am not sure how to control the PWM, I have copied the code from a video, but do not know how to reach maximum and minimum rpm; also I understand the variation between PWM value and RPM is not linear. Any feedback on how to precisely control the rpm of the motor would be great

int IR_signal=2;
int DC_ENB=11;
int DC_IN3=4;
int DC_IN4=5;
int STE_dir=6;
int STE_step=7;
int STE_ena=10;
int button_reset=8;
int button_action=9;
//define arduino pin
int action_permit;//0-action part is not allowed to run. 1-action part is allowed to run
int IRon;
int COUNT;//the amount of steps that the machine head should go
int HEIGHT;//total height that the machine head should go
int i;
int reset_on;
int action_on;
String Switch_DC;

//parameter
void setup() {
  // put your setup code here, to run once:
  pinMode(IR_signal,INPUT);
  pinMode(button_reset,INPUT);
  pinMode(button_action,INPUT);
  //input part
  pinMode(DC_ENB,OUTPUT);
  pinMode(DC_IN3,OUTPUT);
  pinMode(DC_IN4,OUTPUT);
  pinMode(STE_dir,OUTPUT);
  pinMode(STE_step,OUTPUT);
  pinMode(STE_ena,OUTPUT);
  //output part
  action_permit=0;// ban the action part at the beginning
  COUNT=0;
  HEIGHT=0;

  //original value of parameters
  //digitalWrite(DC_ENB,HIGH);
  analogWrite(DC_ENB,200);
  digitalWrite(STE_ena,LOW);
  digitalWrite(DC_IN3,HIGH);
  digitalWrite(DC_IN4,HIGH);
  //original pin output
  Serial.begin(9600);
  // start the monitor
}

void loop() {
  // put your main code here, to run repeatedly:
  reset_on=digitalRead(button_reset);
  action_on=digitalRead(button_action);
  //read the signal from the button
  if(reset_on==0)//reset button is pressed
  {
    delay(10);
    // preventing manual error
    if(reset_on==0)
    {
      RES();
    }
  }
  if(action_on==0)//action button is pressed
  {
    delay(10);
    // preventing manual error
    if(action_on==0)
    {
      ACT();
    }
  }
}
void RES()//reset part
{
  while(action_permit==0)//when 0, this "while" loop will keep running
  {
    IRon=digitalRead(IR_signal);// read the signal from IR sensor
    if(IRon==1)// machine head is not in original position
    {
      delay(1);
      //ensure the signal is not happened by a BUG
      IRon=digitalRead(IR_signal);
      if(IRon==1)
      {
        digitalWrite(STE_dir,LOW);
        digitalWrite(STE_step,HIGH);
        delay(1);
        digitalWrite(STE_step,LOW);
        delay(1);
        //if machine head is not in original position, it will go up for one step
      }
    }//if HIGH, go up
    else if(IRon==0)
    {
      action_permit=1;
      COUNT=0;

    }//once machine head reaches the original position, controller will get out this loop and allow action part to run
  }
}
void ACT()//action part
{
  if(action_permit==1)
  {

   for(i=0;i<3523;i+=1)
   {
     digitalWrite(STE_dir,HIGH);
     digitalWrite(STE_step,HIGH);
     delay(1);
     digitalWrite(STE_step,LOW);
     delay(1);
   }
   delay(100);
   for(i=0;i<100;i+=1)
   {
     digitalWrite(STE_step,HIGH);
     delay(10);
     digitalWrite(STE_step,LOW);
     delay(10);
   }
   action_permit=0;

   Serial.println("Please press y to start tool rotation");
   while((Serial.available()==0))
   {
    //waiting for input
   }
   Switch_DC=Serial.readString();
   if (Switch_DC == "y")
   action_permit=0;
   {
    analogWrite(DC_ENB,200);
    digitalWrite(DC_IN3,HIGH);
    digitalWrite(DC_IN4,LOW);
    delay(2000);
   }

   Serial.println("Please press n to stop tool rotation");
   while((Serial.available()==0))
   {
    //waiting for input
   }
   Switch_DC=Serial.readString();
   if(Switch_DC == "n")
   action_permit=0;
   {
    analogWrite(DC_ENB,200);
    digitalWrite(DC_IN3,LOW);
    digitalWrite(DC_IN4,LOW);
   }
   digitalWrite(STE_dir,LOW);
   for(i=0;i<4523;i+=1)
   {
     digitalWrite(STE_step,HIGH);
     delay(1);
     digitalWrite(STE_step,LOW);
     delay(1);
   }
   action_permit=0;
  }
}

for precise control of motor RPM, you need to use a sensor that generates a pulse, or multiple pulses for one revolution of the motor

You have some obvious problems in your code, though I don't know, if the logic will be correct (doing what you want it to do) if you fix them. But either way it is a good start.

You check for action_on and reset_on to be LOW, so I guess the button will pull the pin to LOW, if you press it. You didn't activate the internal pullup resistors, so I guess you already have them externally (if not: You definitely need them). So action_on==0 actually is the case for action is permitted to run, not forbidden. You seem to think, that it is the other way round.
Then you are doing this (and the same with reset_on):
if(action_on==0)//action button is pressed
  {
  delay(10);
  // preventing manual error
  if(action_on==0)

You check, if action_on is zero. If yes, you wait a bit and check the same again. The value of action_on cannot change during the delay, so this will always be true and thus is superfluous. If you meant to read the button again, to check if the button was really pressed (for debouncing), you have to actually read the button state again with digitalRead() and save it to action_on, like you have done before. This is not done automatically for you.
for(i=0;i<3523;i+=1)  Using a global variable to count in a for loop is not a good idea. Instead you should always use a local variable to do this: for(int i=0;i<3523;i+=1)
Switch_DC=Serial.readString();  Using readString() is not good coding, because this function just reads all data, that comes until the timeout hits (default 1s). This is not a reliable way to read data from Serial. Instead you should read each character individually from the Serial interface, put it into a buffer, and only stop and process the output, if a delimiting character was send. Often a newline character \n is used for this. So one message/command, that should be processed as a whole should be ended with a newline character. That will prevent, that the input from serial is processed incorrectly, only because the timing was different. If you only have commands, that consist of only 1 character, you can instead use a single Serial.read(), which reads exactly one character from the Serial interface (or returns -1 if there is no character to read).
Then you wrote this:
if (Switch_DC == "y")
action_permit=0;
{

I guess, here you have inserted the action_permit=0. This cannot be, want you meant. As you wrote it, the action_permit=0 line will only be executed, if Switch_DC is equal to "y", since this statement is inside the if statement. The ; at the end of the statement also closes the if statement. So the code inside the following brackets will always be executed and the brackets are superflous. I don't know, where you intended to insert the action_permit=0, but since it is never used in the rest of the function, it is sufficient to just use it at the end of the function, like you already did. Remove all other of these lines from that function.

If you want to control the RPM of the motor, not just some relative PWM value, you first need to measure the RPM. PWM just controls the electrical energy going into the motor in a relative way (relative to fully powered on). To set a RPM value for the motor, you need to measure the current RPM (for example with a light barrier or a rotary encoder) and use that as input for a PID controller (Proportional Integral Differential). The output of the PID controller then must be fed into the analogWrite() function. The PID controller will raise or lower the PWM value, until the RPM setpoint is reached. There is a PID library for Arduino, that will help you with the calculation.

A big thank you for your help! I will implement your suggestions one by one and see how the code improves. Your help has enabled me to start thinking like a programer and I can't thank you enough for this. As to respond to the action_permit. Yes its a normally closed button, also when I remove action_permit from any place in the code (I have tried removing it one by one at all places), the lines of code near that statement start misbehaving. In regards to your comment about the reading the input from the user, can you suggest a better alternative as to how to read 'y' and 'n'?  Thankyou again!

hi Chrisl, as for the PWM function. Yes I do have a tachometer. I am not sure if I want to use a PID, can you suggest as to how I can calibrate it manually?

About Serial: As I already wrote in the answer, if you just have commands consisting of 1 byte/character, you can just use Serial.read(), which reads exactly 1 character. About PWM: This is a a typical situation for a control cycle. Using PID is the best here. It get's you the desired output fastest and without oscillation. If you only calibrate the PWM values (mapping PWM values to RPMs by testing), that disregards the load on the motor and will not be accurate. Ultimately it is your decision, what you need. PID with the linked library is not difficult.

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
How do arrays work?
It's been days now I'm trying to figure out how arrays work in Arduino IDE.
For better understanding, I assembled some pieces of code I found here and there to write this sketch:

#define arrayLength(x) (sizeof(x) / sizeof(int)) //array size

typedef struct {
  int note;
  int duration;
} BUZZER_NOTE ;

class Buzzer {

  public:

    BUZZER_NOTE notes[];  //-- Funny how the same declaration tried below DOES work if it's inside a class

};

void setup() {

  Serial.begin(9600);

//  BUZZER_NOTE notes[];  //-- Compilation error:

  int *bob;               //-- Declaring this way, shows no compilation errors, but prints out strange values
//  int bob[];            //-- Compilation error: "storage size of 'bob' isn't known"

  int bob1[] = {10, 20};
  int bob2[5] = {10, 20, 30, 40, 50};
  int bob3[] = {60, 70, 80};

  bob[0] = 10;
  bob[1] = 20;
  bob[2] = 30;
  bob[3] = 40;
  bob[4] = 50;
  bob[5] = 60;
  bob[6] = 70;   //-- No matter how many indexes I create, it will always show lenght of 2

  test(1);       //-- Calls the first function below, as expected
  test({1});     //-- Also calls the first function below, when the second one (with the array parameter) is expected

  test(bob);     //-- Length: 1 (expected 5); Size: 2 (?????) ; First Element: 163 (expected 10);
  test(bob1);    //-- Length: 1 (expected 2); Size: 2 (?????) ; First Element: 10  (ok);
  test(bob2);    //-- Length: 1 (expected 5); Size: 2 (?????) ; First Element: 10  (ok);
  test(bob3);    //-- Length: 1 (expected 3); Size: 2 (?????) ; First Element: 60  (ok);

}

void loop() {
}

void test(int a) {
  Serial.println("Called int function");
  Serial.println();
}

void test(int a[]) {
  Serial.println("Called array function");
  Serial.print("Length: ");
  Serial.println(arrayLength(a));
  Serial.print("Size: ");
  Serial.println(sizeof(a));
  Serial.print("First Element: ");
  Serial.println(a[0]);
  Serial.println();
}

The code above prints out these lines:
Called int function    // as expected

Called int function    // expected array function

Called array function  // as expected
Length: 1              // expected 5
Size: 2
First Element: 163     // expected 10

Called array function  // as expected
Length: 1              // expected 5
Size: 2
First Element: 10      // as expected

Called array function  // as expected
Length: 1              // expected 3
Size: 2
First Element: 10      // as expected

Called array function  // as expected
Length: 1              // expected 5
Size: 2
First Element: 60      // as expected

My goal for now is to achieve something like this:
int bob[]; // this gives a compiler error: "storage size of 'bob' isn't known"
bob = {10, 20, 30, 40};

test(bob);

void test(int arr[]) {
  for (int i = 0; i < FIND_ARR_LENGTH_SOMEHOW; i++) {
    Serial.print("Index i: ");
    Serial.println(arr[i]);
}

Question: How can I declare an array without mention its size, fill it up with as many indexes I want, then pass it to a function that will be able to process all the contents?
I know I could declare an array and keep its length to pass as a second parameter, but there must be a way to get an array length.
Thanks in advance.

https://majenko.co.uk/blog/arrays-pointers-what-c

#define arrayLength(x) (sizeof(x) / sizeof(int)) //array size is wrong! #define arrayLength(x) (sizeof(x) / sizeof(x[0])) might work if x is an array

@Majenko If I had found such an article before, it would have saved me several hours. Thanks a lot.

BUZZER_NOTE notes[];  //-- Funny how the same declaration tried below DOES work if it's inside a class

It doesn't really. C++ language prohibits that. It is just a non-standard quirk of GCC compiler used by Arduino IDE, which happens to support C-style flexible array members in C++ code.

//  BUZZER_NOTE notes[];  //-- Compilation error:

Of course. You are not allowed to use incomplete types in object definitions. And an array of unspecified size is an incomplete type. A widely used exception from this rule is an [] array declared with an initializer. In that case the array size is assumed to be implicitly specified by the initializer.

int *bob;               //-- Declaring this way, shows no compilation errors, but prints out strange values

Of course. This is not an array at all. It is a pointer. And it doesn't point anywhere. It is invalid. You are not allowed to even access such pointer.

//  int bob[];            //-- Compilation error: "storage size of 'bob' isn't known"

See above.

 int bob1[] = {10, 20};
 int bob2[5] = {10, 20, 30, 40, 50};
 int bob3[] = {60, 70, 80};

These are properly declared arrays. As I said above, the [] declaration is allowed since you are declaring your array with an initializer.

bob[6] = 70;   //-- No matter how many indexes I create, it will always show lenght of 2

This does not make any sense at all. You cannot "create indexes" in an array. Array size is fixed at the point of declaration. There's no way to shrink or expand it, there's no way to "create" or "remove" indexes.
But in this example bob is not even an array. It is a pointer. And since it is a garbage pointer that doesn't point anywhere, you are not allowed to access it with any indexes.
Once you make your bob to point to some valid block of memory, you will be able to access it as bob[3] and such, as long as you stay withing the bounds of that block of memory.

test({1});     //-- Also calls the first function below, when the second one (with the array parameter) is expected

Several mistakes here.
Firstly, you second function does not have "array parameter". In parameter declarations int a[] is equivalent to int *a. It is a pointer parameter, not an array parameter.
Secondly, since the beginning of times in C and C++ you could use a scalar value in {} to initialize a scalar object
int a = { 42 }; /* <- this has always been legal in C and C++ */

So, the first function is obviously a candidate in this case. The rules of C++ language dictate that {1} initializer can be used as an initializer for an int value or std::initializer_list<int> object, but for a pointer. Which is why the first function is called.
You can force it to produce a temporary array through array-type alias and functional-cast syntax
using ARR = int[];
test(ARR{1});

but in GCC you will run into a GCC bug preventing you from forming pointers and references to temporary arrays (Clang will accept it).

void test(int a[]) {
  ...
  Serial.print("Length: ");
  Serial.println(arrayLength(a));

This makes no sense. This "array length" trick
#define arrayLength(x) (sizeof(x) / sizeof(int))

only works with arrays. Your a inside test is not an array. It is a pointer. It is completely pointless to apply this sizeof trick to a pointer.

My goal for now is to achieve something like this:
int bob[]; // this gives a compiler error: "storage size of 'bob' isn't known"
bob = {10, 20, 30, 40};

Not possible. When defining an array, you always have to specify a fixed compile-time size. And arrays in C and C++ are not copyable, not assignable. If you want to copy data between arrays, you have to either do it manually, element by element, or use a library-provided routine that does the same.
{}- initializers can be used with arrays, but only at the point of declaration. Not later. You can do something like
using A = int[5];
A a;
std::memcpy(a, A{1, 2, 3, 4, 5}, sizeof(A));

but this will run into the same GCC bug I mentioned above.
On a related note: standard library provides std::array template - a thin wrapper for raw arrays. std::array objects are copyable and assignable through a pretty much the same syntax as you used
std::array<int, 5> a;
a = { 1, 2, 3, 4, 5 };

But they are still arrays of fixed compile-time size.

void test(int arr[]) {
  for (int i = 0; i < FIND_ARR_LENGTH_SOMEHOW; i++) {

Not possible. Your arr is a pointer. It is not possible to extract "array size" information for a pointer, since that information simply does not exist. If you want to "FIND_ARR_LENGTH_SOMEHOW" you have to either develop your own convention for finding that length or simply pass that length to the function through a separate parameter.

I apologize for the silly question. I'm not used with c / c++ programming and was just trying to write a library while I learn nothing. Never really had to deal with pointers with the languages I'm used to.
Anyways, your explanations are pretty enlightening. I will have to dig some more about pointers and memory stuff.
Thank you.

This is more of a general programming question, but since there are some special pitfalls for microcontrollers/Arduinos I will answer the question.

How can I declare an array without mention its size, fill it up with as many indexes I want, then pass it to a function that will be able to process all the contents?

Short answer: You cannot. An array has always a fixed size, that cannot be changed during the lifetime of the array.
Long answer: Though every array has it's fixed size, you can create new arrays with a size, that is not known at compilation time. For this you would need dynamic memory allocation like done with the new keyword:
BUZZER_NOTE *notes = new BUZZER_NOTE[x];

with the size of the new array x. notes is here a pointer to the array (actually a pointer to the first element of the array). If you don't know, how to deal correctly with pointers, you should google for a tutorial about it, there are plenty on the web. So, if your defined array is full and you want to add more elements, you have to define a new array with bigger size, copy the old content and delete the old one (actually that is what happens inside the String class).
To actually get the easy way of adding more elements, without copying the whole content, a C++ programmer would use a linked list. This defines an element class, that contains a variable for the content of the element and a pointer to the next element in the list. So to iterate through the linked list, you would start at the first element and follow the pointers through the list to the end. (Again you can read more about this concept on the web)
BUT: You should not use any of these things on an Arduino, especially not on the ones with very limited RAM (like Uno, Nano, ...). When you do dynamic memory allocation, memory fragmentation will happen. Take the example from above. You have a dynamically allocated array with your data. Now you want to store more data. You define a new and bigger array. For the simplicity of explanation, it will be allocated directly after the first array in the memory. You copy the content and delete the first array to free the memory. Now there is free space in your memory with the size of the first array. Now you want to again add more data, so you define a new and bigger array. This array cannot fit into the free space at the start, since the space to not big enough. This memory space is now dead, because it cannot be used for your data.
In real cases, you would allocate and delete variables with varying sizes throughout your sketch. This leads to the point, that you will get many holes in your memory, which are too small to fit your data in. On a PC this is not a big problem, since you have a lot of RAM and the OS can reorganize the data to fit better. But on the Arduino you have only very limited RAM and no OS, so you quickly run out of RAM. Your sketch will stop to work at that point, since there is no usable memory left on the device.
You instead should go the harder way and just use fixed arrays, that are big enough to hold the biggest amount of data, that you expect.

And since AnT didn't cover this completely:
bob[6] = 70;

This line cannot work correctly for 2 reasons: First you only declared bob as a pointer, but this pointer does not point to a valid memory address. You would have to create a corresponding array with the new keyword as shown above, or let it point to an existing array. Currently you try to write to an invalid or random memory address.
Secondly the compiler cannot know, how many items the array has, that bob should point to. This is just not an information, that the compiler has. So it will not prevent you from writing higher indices, than are in the array. But effectively the memory write either fails, because the address of the non-existent element is invalid, or you will overwrite data from some other variables --> Very dangerous! It is your responsibility to ensure, that you don't write data, where it does not belong.
And keep in mind, that microcontrollers don't have something like exceptions. Thus some things, that would through an exception on a PC will stop the microcontroller from working, or it will just do the crazy stuff, that you told him to do (where accessing memory outside of the array would through a runtime error on the PC).

Yeah, that makes a whole lot of sense. I'm trying to write a general purpose library for NodeMCU, which has a lot of memory (I guess) and that wouldn't be an issue.
But considering I could be using it in other projects for other Arduino models, your answer clarifies a lot of things.
Thanks.

Ok, after reading and reading the answers and links about my question, I ended up using a function as suggested. Something like:
void foo(char* myArray, int size) {}

But I ended up finding another solution to the problem, which is a little more complicated:
#define arrayLen(x) (sizeof(x) / sizeof(x[0]))

char myArray[64] = "my array test with a long value in it";

void setup() {

  Serial.begin(9600);
  while (!Serial);

  // IMHO, it would be nice if the compiler would accept these two sintaxes
//  myArray = "my array test with a long value in it";
//  "my array test with a long value in it".toCharArray(myArray, 64);

  Serial.print("Value before: ");
  Serial.println(myArray);
  Serial.print("Size before: ");
  Serial.println(arrayLen(myArray));

  String temp;
  temp = myArray;

  foo(temp);

  Serial.print("Value after: ");
  Serial.println(myArray);
  Serial.print("Size after: ");
  Serial.println(arrayLen(myArray));

}

void loop() {}

void foo(String str) {
  for (int i = 0; i < str.length(); i++) {
    Serial.print("Index ");
    Serial.print(i);
    Serial.print(": ");
    Serial.println(str.charAt(i));
  }
}

I know I have a bad habit to use Strings instead of array of chars (coming from other languages), but in this example, memory limitation issues won't be significant because the String will be freed from memory after execution of setup() and foo().
There is another thing I would like to share (not directly related to my previous question), that I believe could be useful for other people.
This little sketch shows how to use the same String technique to manipulate the contents of a char array, passed by reference to an external function. Here it goes:
#define arrayLen(x) (sizeof(x) / sizeof(x[0]))

char myArray[64] = "my array test with a long value in it";

void setup() {

  Serial.begin(9600);
  while (!Serial);

  Serial.print("Value before: ");
  Serial.println(myArray);
  Serial.print("Size before: ");
  Serial.println(arrayLen(myArray));

  String temp;
  temp = myArray;

  foo(temp);
  temp.toCharArray(myArray, 64);

  Serial.print("Value after: ");
  Serial.println(myArray);
  Serial.print("Size after: ");
  Serial.println(arrayLen(myArray));

}

void loop() {}

void foo(String &str) {
  str = "abcde";
}

Results (just as expected):
Value before: my array test with a long value in it
Size before: 64
Value after: abcde
Size after: 64

It may look awful to the eyes of a C++ programmer, but hey, it works!
Thanks again for all the answers/comments.

The C arrays are tricky and they're described in every C tutorial. The other answers adresses mistakes / questions in comments, but none of them shows how it can be done:

struct BuzzNote {
  int note;
  int duration;
};

const BuzzNote melody[] = {
  {10, 200}, { 45, 300}, {90, 200}, // ...
};

void test(BuzzNote const * arr, size_t len) {
  for (size_t i = 0; i < len; ++i) {
    Serial.print(i);
    Serial.print(". ");
    Serial.print(arr[i].note);
    Serial.print(' ');
    Serial.println(arr[i].duration);
  }
}

// using template for determining size of array
// (and as a bonus it won't work with plain pointers)
template<typename T, size_t size>
size_t GetArrLength(T(&)[size]){return size;}

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

void loop() {
  test(melody, GetArrLength(melody));
  delay(10000);
}

I'm using template version of getting array length (it won't compile with pointers, as pointer isn't array).
And this version stores data in RAM (and waste it). If you don't have spare space in ram, you'll have to dig into PROGMEM variables/arrays. But it's the quest for another day :D

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
ESP8266 + Slack (ssl->need_bytes=16432 > 6859)
I'm trying to connect an Adafruit Huzzah ESP8266 with Slack.
I'm facing an issue with the connection I'd like some help or tips on.  I'm able to get a connection sometimes, but sometimes during the initial step where I'm making the first connection, I get errors and it completely fails, repeating the connect/disconnect over and over again.
The error I get is usually this:
ssl->need_bytes=16432 > 6859

My Troubleshooting So Far
As per this github issue:
https://github.com/esp8266/Arduino/issues/1375
My understanding is that the error is caused by Slack's SSL certificate being too large.  This makes sense, but sometimes my code (see below) actually works which is why I'm confused.
When it does work, it usually fails a couple times at first, before maintaining a consistent ping with Slack.  At that point, it works as expected, and I can send commands from Slack to the board without fail.

Does anyone have an idea why this sometimes works, and sometimes doesn't?
I'm assuming it has something to do with the SSL certificate size being too large, but if that was the case why wouldn't it fail each time, but work sometimes?
Any help is greatly appreciated.

Errors in Serial Monitor
Here's what I see in the Serial Monitor log:
⸮scandone
f r0, scandone
f r0, scandone
state: 0 -> 2 (b0)
state: 2 -> 3 (0)
state: 3 -> 5 (10)
add 0
aid 7
cnt

connected with 2WIRE952, channel 3
dhcp client start...
ip:192.168.1.73,mask:255.255.255.0,gw:192.168.1.254

Waiting for time sync
please start sntp first !
.please start sntp first !
.Sun Apr 16 06:57:35 2017

Time is synced
ssl->need_bytes=16432 > 6859
WebSocket Host=mpmulti-4pcb.slack-msgs.com Path=/websocket/Z5ZDermv9h2Q7HL88ukG5ddIvY--zrBAVCN4423KOy5t_6wN3AW859grAYCYr6L-0l0leeXA3AhlO1VmIxcCopS1pJ-IkrVOdmel50tgcA7hBJwEIkpI-biYnraTFc88K4F6wqL3TE_gi1jU0SJHhR6_aD5435yE8FRALEflTkY=
[WebSocket] Connected to: /websocket/Z5ZDermv9h2Q7HL88ukG5ddIvY--zrBAVCN4423KOy5t_6wN3AW859grAYCYr6L-0l0leeXA3AhlO1VmIxcCopS1pJ-IkrVOdmel50tgcA7hBJwEIkpI-biYnraTFc88K4F6wqL3TE_gi1jU0SJHhR6_aD5435yE8FRALEflTkY=
[WebSocket] Disconnected :-(
ssl->need_bytes=16432 > 6859
WebSocket Host=mpmulti-eavp.slack-msgs.com Path=/websocket/HjuUTJUL4ghmBCthwdFxOYNWD0wGjWbCgQZwnum546F5Nj8rrJ7LJgeyVOLqSv9sBHtkZBrCBLyxdM2oMB85-GXGwtIgg9anVYFL66vMB8yEN9Xout7OMmqlEewZsL7n2vqJyvx_qAnQ9M8UwOnZwETkNYJ51XrUvR6EjIAvAQE=
[WebSocket] Connected to: /websocket/HjuUTJUL4ghmBCthwdFxOYNWD0wGjWbCgQZwnum546F5Nj8rrJ7LJgeyVOLqSv9sBHtkZBrCBLyxdM2oMB85-GXGwtIgg9anVYFL66vMB8yEN9Xout7OMmqlEewZsL7n2vqJyvx_qAnQ9M8UwOnZwETkNYJ51XrUvR6EjIAvAQE=
[WebSocket] Disconnected :-(
ssl->need_bytes=8496 > 6859

My Sketch Code
The Sketch file I'm compiling using the Arduino IDE.
Note: be sure to update Wifi + Slack Bot Token if testing  8-)

#include <Arduino.h>

#include <ESP8266WiFi.h>
#include <time.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>

#include <WebSocketsClient.h>
#include <ArduinoJson.h>

#define SLACK_SSL_FINGERPRINT "AC 95 5A 58 B8 4E 0B CD B3 97 D2 88 68 F5 CA C1 0A 81 E3 6E" // If Slack changes their SSL fingerprint, you would need to update this

#define WIFI_SSID       ""
#define WIFI_PASSWORD   ""

String SLACK_BOT_TOKEN = ""; // Get token by creating new bot integration at https://my.slack.com/services/new/bot

#define WORD_SEPERATORS "., \"'()[]<>;:-+&?!\n\t"

ESP8266WiFiMulti WiFiMulti;
WebSocketsClient webSocket;

long nextCmdId = 1;
bool connected = false;

//Timezone Settings
const int timezone = 9;
const int dst = 0; //daylight savings

/**
  Sends a ping message to Slack. Call this function immediately after establishing
  the WebSocket connection, and then every 5 seconds to keep the connection alive.
*/
void sendPing() {
  DynamicJsonBuffer jsonBuffer;
  JsonObject& root = jsonBuffer.createObject();
  root["type"] = "ping";
  root["id"] = nextCmdId++;
  String json;
  root.printTo(json);
  webSocket.sendTXT(json);
}

/**
  Looks for color names in the incoming slack messages and
  animates the ring accordingly. You can include several
  colors in a single message, e.g. `red blue zebra black yellow rainbow`
*/
void processSlackMessage(char *payload) {
  char *nextWord = NULL;
  bool zebra = false;
  for (nextWord = strtok(payload, WORD_SEPERATORS); nextWord; nextWord = strtok(NULL, WORD_SEPERATORS)) {
    if (strcasecmp(nextWord, "red") == 0) {
      Serial.printf("Yay! Its red.");
    }

  }
}

/**
  Called on each web socket event. Handles disconnection, and also
  incoming messages from slack.
*/
void webSocketEvent(WStype_t type, uint8_t *payload, size_t len) {
  switch (type) {
    case WStype_DISCONNECTED:
      Serial.printf("[WebSocket] Disconnected :-( \n");
      connected = false;
      break;

    case WStype_CONNECTED:
      Serial.printf("[WebSocket] Connected to: %s\n", payload);
      sendPing();
      break;

    case WStype_TEXT:
      Serial.printf("[WebSocket] Message: %s\n", payload);
      processSlackMessage((char*)payload);
      break;
  }
}

/**
  Establishes a bot connection to Slack:
  1. Performs a REST call to get the WebSocket URL
  2. Conencts the WebSocket
  Returns true if the connection was established successfully.
*/
bool connectToSlack() {
  // Step 1: Find WebSocket address via RTM API (https://api.slack.com/methods/rtm.start)
  HTTPClient http;
  http.begin("https://slack.com/api/rtm.start?token=" + SLACK_BOT_TOKEN, SLACK_SSL_FINGERPRINT);
  int httpCode = http.GET();

  if (httpCode != HTTP_CODE_OK) {
    Serial.printf("HTTP GET failed with code %d\n", httpCode);
    return false;
  }

  WiFiClient *client = http.getStreamPtr();
  client->find("wss:\\/\\/");
  String host = client->readStringUntil('\\');
  String path = client->readStringUntil('"');
  path.replace("\\/", "/");

  // Step 2: Open WebSocket connection and register event handler
  Serial.println("WebSocket Host=" + host + " Path=" + path);
  webSocket.beginSSL(host, 443, path, "", "");
  webSocket.onEvent(webSocketEvent);
  return true;
}

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

  WiFiMulti.addAP(WIFI_SSID, WIFI_PASSWORD);
  while (WiFiMulti.run() != WL_CONNECTED) {
    delay(500);
  }

  //setup network time protocol (ntp)
  configTime(timezone * 3600, dst, "pool.ntp.org", "time.nist.gov"); //configtime is esp8266 function

  Serial.println("\nWaiting for time sync");
  while (!time(nullptr)) {
    Serial.print(".");
    delay(1000);
  }
  Serial.println("Time is synced");

  delay(500);
}

unsigned long lastPing = 0;

/**
  Sends a ping every 5 seconds, and handles reconnections
*/
void loop() {
  webSocket.loop();

  if (connected) {
    // Send ping every 5 seconds, to keep the connection alive
    if (millis() - lastPing > 5000) {
      sendPing();
      lastPing = millis();
    }
  } else {
    // Try to connect / reconnect to slack
    connected = connectToSlack();
    if (!connected) {
      delay(500);
    }
  }
}

it probably works sometimes becuase you happen to have enough RAM at that moment. You can try reducing RAM usage with the F() macro on long stings, and removing any libs you don't need. The sure-fire way is to proxy the request to slack using something like a php server with a smaller SSL cert; you then talk to the PHP box instead of slack, and it relay's the request/response back to the ESP.

@dandavis - I think you're spot on.  Reducing the amount of code in the Sketch and testing again makes it more reliable, but simply not enough still to ensure 100% bulletproof.  The response back from Slack is simply too large to handle.  I'm just going to use a Raspberry Pi to communicate with Slack, and then send the commands down to an Arduino.

@Axel, the PI actually also has GPIO pins (3.3V!) and should be able to handle basic I/O, so you might even consider letting out the Arduino.

@Paul - I actually ended up using a Raspberry PI Zero W which ended up having the memory requirements that could handle my API calls, and all the other functionality built such as WIFI and GPIO pins.  Not bad for a $10 board.

@Axel Arduino's are development boards for microcontrollers which is a quite different thing. If you're going to mass produce, using microcontrollers (the chip on the Arduino itself) works very well (stable, reliable, cheap, small).

@Paul - I understand the differences.  But coming back to the topic of my question - the Arduino board I was using did not have the memory requirements for the project I was building.  My issue had nothing to do with 3.3V GPIO pin availability as your first comment stated.  I already knew the Arduino had those :P

Also - this isn't for mass production.  It was a one-off project for personal use ;)

replace rtm.start with rtm.connect as per April 2017 Recent Updates log

authors: Трудове Навчання 5-11


text:
Bootloader fails when two Arduinos are connected over serial port
I’d like to connect two Arduinos over serial port so that they can communicate with each other. Initially, I put all necessary code onto one device and now connected another via serial port. As soon as I connected the second one I lost the ability to upload new code onto the first one. I’m certain they are conflicting over serial pins. I tried to hold reset on the second Arduino, but it didn’t help. The only way to flash it back again with avrdude is to disconnect the second one.
Is there a way to get this setup working with serial bootloader without disconnecting pins? Thanks for your ideas.
I do not use the Arduino IDE. I believe that if someone has a solution for Arduino it will work for me. I use Atmel Studio 7 with avr gcc. The boards are Chinese clones with ATMega328P on them flashed with the optiboot bootloader. Pins connected are TxD and RxD to opposites on the second board. They are powered from the same power supply. This question is not how to communicate with another Arduino. This question is how to still be able to flash one Arduino while something else is connected to its serial port. I know that the USB to serial bridge IC is connected, but this is a standard setup on all Arduinos that have no embedded USB controller.
Board is Arduino Nano v3 clone with CH340 USB<->UART chip. Both boards work OK by themselves, once connected together they stop responding to avrdude. The connection is as following. Length of connection is only 15cm.
Nano v3 (1)        |          Nano v3 (2)
    |              |              |
RX0 o-----+------~ ~ ~------+-----o TX1
    |     |        |        |     |
TX1 o---+-|------~ ~ ~------|-+---o RX0
    |   | |        |        | |   |
      --o-o--      |      --o-o--
       CH340       |       CH340
         ^         |         ^
         |         |         |
        USB        |        USB

Which Arduino boards do you use, and which pins did you connect? Do you want to upload a sketch while the two Arduino boards are connected? Did you also connect the grounds? Please update your question with the extra information. The Atmega328p has only one serial port, and that is used to upload a sketch and for the serial monitor. How much data do you want to transfer between the Arduino boards?

Could you give a link to that clone board please. Do you have a schematic of that clone board? Is it a Arduino Pro Mini clone? Holding reset on the second board should help, so it must be something else in the circuit or wiring or perhaps a cable that is too long (the bootloader has its own baudrate).

Truly holding reset should work, but beware that the traditional UART header on the end of the board doesn't have true reset input, but just a path through a capacitor to momentarily blip reset via a serial control signal.  It's also possibly you have TX/RX backwards for the board you are targeting, or that you've failed to accomplish a timely reset of the target.

Now we know that it is a Arduino Nano board. That board has a usb-serial chip on the board. Those are also connected to rx and tx. One signal line has rx of one CH340G connected and the tx of the other CH340G chip and the other line has also a rx and a tx of a CH340G. I think that the tx of the unused CH340G is the problem. The Arduino (Pro) Micro has a spare serial port, so do the Arduino Zero and Due and the Arduino Mega 2560. I2C is possible. You could perhaps use 4 wires and create your own asynchroon communication with handshake. Why do you need two Arduino boards in the first place?

@Jot I think you're right. I have no issues with just rx pin connected from second board. Once I connect 'tx' pin it fails. tx pin of the second board has some potential, which I think confuses first CH340G. I reset both boards, but keep holding reset on the second board, and I was able to upload HEX file onto the first one.


text:
Has anyone modified a 16x2 LCD shield to work with Arduino DUE?
Since the DUE works on 3.3 volts has anyone successfully modified a 5V 16x2 LCD shield to work with Arduino DUE?  I'm thinking 3.3V will be seen as a logic "1"
by the 5V LCD shield and there are no 5V outputs that feed back to the 3.3V due if the R/~W line on the LCD is simply grounded.
Would love to hear anyone's opinion on this.
Thanks,
Charlie

Is the R/W line broken out, or always connected to ground? During startup the pins are floating, which the lcd might interpret as a HIGH, outputting 5V to the data pins. You could add an external pull-down resistor to that pin, just to be safe. Other than that, you are totally correct. No problem.

I understand this is an 8yo thread, however my answer might still help someone.
I connected an unmodified no-brand LCD Shield to an Arduino DUE and it works perfectly - the only thing I had to change was the analog thresholds to identify the buttons. Just upload the sketch and read out the real values on the display then enter the averages between adjacent buttons in read_LCD_buttons function.
//Sample using LiquidCrystal library
#include <LiquidCrystal.h>

/*******************************************************

This program will test the LCD panel and the buttons
Mark Bramwell, July 2010

********************************************************/

// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// define some values used by the panel and buttons
int lcd_key = 0;
int adc_key_in = 0;
#define btnRIGHT 0
#define btnUP 1
#define btnDOWN 2
#define btnLEFT 3
#define btnSELECT 4
#define btnNONE 5

// read the buttons
int read_LCD_buttons()
{
adc_key_in = analogRead(0); // read the value from the sensor

if (adc_key_in < 90) return btnRIGHT;
if (adc_key_in < 297) return btnUP;
if (adc_key_in < 533) return btnDOWN;
if (adc_key_in < 814) return btnLEFT;
if (adc_key_in < 1000) return btnSELECT;

return btnNONE; // when all others fail, return this...
}

int button_count=1;

// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 13;

int i;

void setup()
{
lcd.begin(16, 2); // start the library
lcd.setCursor(0,0);
lcd.print("Push the buttons"); // print a simple message

// initialize the digital pin as an output.
pinMode(led, OUTPUT);

}

void loop()
{
  delay(100);
  lcd.setCursor(9,1); // move cursor to second line "1" and 9 spaces over
  lcd.print("        ");
  lcd.setCursor(9,1); // move cursor to second line "1" and 9 spaces over
  lcd.print(analogRead(0)); // display A0 analog input to calibrate values

  lcd.setCursor(0,1); // move to the begining of the second line
  lcd_key = read_LCD_buttons(); // read the buttons

  switch (lcd_key) // depending on which button was pushed, we perform an action
  {
    case btnRIGHT:
        lcd.print("RIGHT ");
        button_count = 2;
        break;

    case btnLEFT:
        lcd.print("LEFT ");
        button_count = 3;
        break;

    case btnUP:
        lcd.print("UP ");
        button_count = 4;
        break;

    case btnDOWN:
        lcd.print("DOWN ");
        button_count = 5;
        break;

    case btnSELECT:
        lcd.print("SELECT");
        button_count = 6;
        break;

    case btnNONE:
        lcd.print("NONE ");
        button_count = 1;
        break;
  }

}


text:
Is there an Adafruit function to invert the colors of my screen for Arduino language?
I am trying to invert the color of my OLED display screen once a button is pushed. I have the button situation figured out but I can not find a function that inverts the color. I am using these two libraries to handle my screen on the Arduino IDE.
Adafruit_GFX.h, Adafruit_SSD1306.h
Any help would be much appreciated.

When there is no such function in these libraries, then there is most likely not an Adafruit function for that. You will have to do it yourself. It depends on what exactly means inverted here. koronas answer to this question on stackoverflow states, that you just need to invert the bits of the color components. The question is about C#, but the syntax in the answer is the same in C++. Please try, if that does, what you want.

Another answer of that question states, that you would need to do a transformation in the HSV color space.

There is a function that invert the colors of your screen, you can pick either black on white or white on black, I have tried it and I have quite experience with your display, I think you should try this piece of code.
At the beginning of your Arduino code be sure that you declared the object using the same name.
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

To invert the display
display.invertDisplay(true);

To return the display again
display.invertDisplay(false);

As you said that you want a button to invert the display you might use this code I made
if(digitalRead(BUTTON_PIN)){
    display.invertDisplay(true);
}
else{
    display.invertDisplay(false);
}

Or you might use Interrupts for better performance depending on your code.
As you couldn't find on the internet, I am student and I learn alot from the internet, to for example search for such a function in an Arduino library, try searching it's documentation or it's page on GitHub then afterwards see the function you want through the pages, but don't just search the function directly it will sometimes won't work as they are not that popular.
As a last thing Here is the documents where I got the function with it's parameters from.
I hope I've helped you out. any edits in the answer is well appreciated, as I am a student.


text:
Use an Arduino Mega in a incubator (high humidity)
I wonder whether it is possible to use an Arduino Mega in a cell incubator.
In the incubator there is a temperature of 37°C, 5% CO2 in the atmosphere and a high relative humidity of around 95% - 98%. I think the temperature (specs of ATmega2560, temperature range: -40 °C to 85 °C) and the CO2 is no problem.
But I am concerned the condensation due to the high humidity will cause damage.
One mitigation could be, that I first pre-warm the Arduino Mega so it doesn't condensate.
(There is a possibility that I don't put the Arduino in the incubator at all, but it would be easier if I could).

The condensation is a real problem. Don't put an Arduino Mega inside an incubator. Why use such a big board? Perhaps a smaller board that can be potted in something might work, but perhaps others know about that.

Put the mega in a ziplock bag. Only have the wires stick out.

You could try a DIY conformal coating spray, read the label to see if it will do what you want.  If you have the budget then there are companies that will do a proper job, but it won't be cheep.  I would also worry about the temp.  You will need to make sure you can dissipate the heat from the board quickly and without messing up the temp of you incubator.

Why would it be so much easier to put it in the incubator?

I did the same this 2 years ago and had problems with co2 sensor mostly.
Which one do you use?

"-40 °C to 85 °C" for the processor, yes, for the other parts, who knows?
The board doesn't get that hot unless you are powering from like a 12V source, and then it's just the regulator that gets hot.
You could a spray-on conformal coat, Mouser.com carries them. Insert any wires into the headers you will use and cover any headers you may want to use before you spray, if you get coating down into the female headers you may have poor contact later on.
The ziplock bag idea sounds like a good start as a start, put some silicon along the seal to fill the holes where the zipper won't close right next to the wires.


text:
I want to make my stepper motor work for 1 hour
I already tried code that makes the stepper motor work for a few minutes only. I'm using a clock module, a DS1302 and the stepper library already present. Also the driver I'm using is an L298n. If someone could help out it would be nice. Thanks.
#include <Stepper.h>
#include <virtuabotixRTC.h>

virtuabotixRTC myRTC(5, 6, 7);
const int stepsPerRevolution = 200;
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);

const int OnHour = 12;
const int OnMin = 52;
const int OffHour = 12;
const int OffMin = 55;

void setup() {
  Serial.begin(9600);
  myStepper.setSpeed(100);
}

void loop() {
  myRTC.updateTime();
  Serial.print(myRTC.dayofmonth); //You can switch between day and month if you're using American system
  Serial.print("/");
  Serial.print(myRTC.month);
  Serial.print("/");
  Serial.print(myRTC.year);
  Serial.print(" ");
  Serial.print(myRTC.hours);
  Serial.print(":");
  Serial.print(myRTC.minutes);
  Serial.print(":");
  Serial.println(myRTC.seconds);
  if (myRTC.hours >= OnHour && myRTC.minutes >= OnMin && myRTC.hours <= OffHour && myRTC.minutes < OffMin) {
    Serial.print(myRTC.hours);
    Serial.print(":");
    Serial.print(myRTC.minutes);
    Serial.print(":");
    Serial.println(myRTC.seconds);
    myStepper.step(stepsPerRevolution);
  }
}

The problem you have is you are treating minutes and hours separately. That won't work - they need to be combined.  As it stands your "on" time is:

Minutes greater than W, and
Hours greater than X, and
Minutes less than Y, and
Hours less than Z.

Or, to rearrange that:

Hours between X and Z, and
Minutes between W and Y.

You can see that won't work. You will only get "on" for the block of minutes between W and Y for each hour in your "ON" period.
For example, if you want ON from 9:30 to 12:45, you get:

If hours greater than or equal to 9 and less than or equal to 12, and
Minutes greater than or equal to 30 and less than or equal to 45

So, that's 9:30 to 9:45, 10:30 to 10:45, 11:30 to 11:45 and 12:30 to 12:45
Even worse if you want 9:30 to 12:00...  the second part of the IF above becomes:

Minutes greater than or equal to 30 and less than or equal to than 0.

That can never happen. There is no number that is both greater than 30 and less than 0.
So you have to combine the two values together, to create a "minutes since midnight" value. Then your ON time is decided by the number of minutes, not the hours and the minutes separately.  It's simple enough:
int minutesSinceMidnight = myRTC.hours * 60 + myRTC.minutes;

Your ON time then becomes, for 9:30, 9 * 60 + 30 = 570, to 12:00 = 12 * 60 + 0 = 720.
So:
if (minutesSinceMidnight >= 570 && minutesSinceMidnight <= 720) {
    // Do your stepping
}


text:
ESP32 - DeepSleep loop or not?
I'm trying to create a battery & solar-powered ESP32 for future use with sensors.
It connects to Wifi, MQTT, publishes some readings and status messages and goes back to sleep. From time to time (it can happen after a few sleep cycles and sometimes after a few hundred cycles), I get 2 unexplained behaviours: 1) fails to connect to MQTT at boot, 2) fails to sleep.
Sometimes those behaviours happen simultaneously.
Is there a known issue with deepsleep and MQTT (using PubSubClient)? Most deepsleep examples I see online, all code is outside the loop() section - is it mandatory to be like that?
I don't share code, since it is more a general question.
Guy
EDIT1

most of callback was commented out, leaving only printing the incoming message.

LED was attached to a GPIO, generating a blink on loop() - when sleep succeeds - it goes off, when it fails, it stays on. This test shows that when this "error" happens, code actually stop running, but does not enter deep sleep (power-wise).

skip the call to MQTT publish to see if the device still fails to sleep .... skip the call by doing a calculation such as if (a+1 == 2) {, not by commenting the line, because commenting the line would cause the compiler to generate different code ........ do the same with the sleep code

@jsotola just to understand  - a+1 should create a logic state that wont enter the if loop to void publish ? and the other part to the esp_deep_sleep_start(); ? I dont understand why so... by the way- see edit 1/

if you use a comment mark // to prevent the MQTT publish command from running, then the compiler will produce different code that may not have the sleep problem .... using an if statement makes sure that the compiler does not skip un-executed code ..... do the same kind of a test for the sleep code to see if it is affecting the MQTT code ...... do the tests separately

@jsotola - I understood the reason why to do this, I asked only for the sleep part. by the way - the publish  workaround did not work, even not when I increased MQTT_MAX_PACKET_SIZE to 512 to be sure

@jsotola for the second check ( "masking" sleep phase ) - all went as expected. In order to cause "reboots" a ESP.restart() every 30 sec was added to loop()

Is there a known issue with deepsleep and MQTT ?

No. There may be a specific problem with the specific library you are using, but the concept of there being an issue with MQTT in general is nonsense.

Most deepsleep example I see online, all code is outside loop()section - is it mandatory to be like that ?

No, that's just being structured and tidy with your code. Whether code is in loop or in functions that are called by loop makes no difference. It can be a lot easier to manage your code if you structure it in functions rather than dumping it all in loop.

I don't know about the nonsense, but s similar question was asked in https://github.com/knolleary/pubsubclient/issues/634 ( same behviour, but case is still open... )

MQTT is just a protocol. The concept of it having a problem makes no logical sense. If there is a problem that is related to using MQTT then it's a problem with pubsubclient not MQTT.

OK, I agree, I ment to pubsubClient

The problem with calling ESP.deepSleep(xx) inside loop() is that watchdog is already activated there, and then a reset occurs during the sleep state.
To fix this, I used the software's own ESP.restart() reset technique after having written a signature to a "not init" variable, as follows:
Variable area:
uint16_t SleepSign __attribute__((section(".noinit"))); // Hot reset / deep sleep signature.

Then, at the beginning of setup() we write the code that tests the content of that uninitialized variable, and if it contains the signature, ESP.deepSleep(xx) is called. In my case I use ESP.deepSleep(0) because I intend for the device to reboot only on a new boot:
void setup()
{
     if (SleepSign == 0xdd11) ESP.deepSleep(0);
     Rest of the initialization:
     ...

Inside loop():
     ...
     if ((millis() - timeconnect) > 300*1000) {
       SleepSign = 0xdd11; // deep sleep at restart
       ESP.restart();
     }
     ...

This system is tested and works correctly, reducing consumption to the minimum specified by espressif. I previously tried to block watch before exiting setup(), but it didn't work, of course:
*((volatile uint32_t*) 0x60000900) &= ~(1); // Hardware WDT OFF

Obviously, if we are interested in using a timed deepSleep, and have the device do anything before going back to sleep, we can assign several values to the SleepSign variable to control the restart, also resetting its value before calling ESP.deepSleep(0):
 void setup()
 {
 if (SleepSign == 0xdd11) {
    SleepSign = 0xffff;
    ESP.deepSleep(xx);
  }
  Rest of the initialization:
  ...

The only drawback I find is that the esp will perform a reset before going to sleep, but I don't think that matters much.


text:
Too slow start up with Atmega2560 on custom PCB
I have some several custom PCB's based on Atmega 2560.
I am using AVRISP MarkII for flashing. No bootloader.
Flashing is flawless, it just works. I have one assembled PCB works as it should be, no issues.
But, the other one has a quite time lag in its functions.
It has also been flashed OK but, it is not running quite OK.
Here are my observations;
By asserting Reset, I expect four leds on the pcb running (on and then off) by 100ms intervals one after each others. This is happening in the very beginning in Setup() section of the program.
Note that: Leds are connected to MCU via mosfets. If MCU output is LOW, they are ON and vice versa.
So, with this problematic PCB, all leds come ON all together after 10 seconds after pressing reset button and they stay almost 60 seconds before they start the sequence (on and then off) as coded.
And then that sequence is also slowly occurring. It is not 100ms as I coded but almost 4 seconds or so.
I am suspecting from the external clock (16Mhz) circuitry but I can't proof it accurately as I don't have oscilloscope at hand.
You may see the simple code I use to test that behavior;
void TestLeds() {
    unsigned long interval = 100;

    digitalWrite(LED1_PIN, LOW);
    delay(interval);
    digitalWrite(LED1_PIN, HIGH);
    delay(interval);

    digitalWrite(LED2_PIN, LOW);
    delay(interval);
    digitalWrite(LED2_PIN, HIGH);
    delay(interval);

    digitalWrite(LED3_PIN, LOW);
    delay(interval);
    digitalWrite(LED3_PIN, HIGH);
    delay(interval);

    digitalWrite(LED4_PIN, LOW);
    delay(interval);
    digitalWrite(LED4_PIN, HIGH);
}

How/where should I check the bottle-neck on that?
Thank you.
EDIT:
To be more specific, I add this output regarding programming;
here

Measure voltage and current.

Did you change the fuses? By default most AVR run at 1MHz from the factory. So that would mean your code runs 16 times as slow.

@Gerben  You mean a sixteenth of the speed, not sixteen times as slow. Sixteen times as slow as what?

I am just using same setup (fuses) as I used for the other PCB. But, how about this: if the external oscillator (16Mhz) doesn't work for some reason although the flashing has just worked fine, could there be something happened about the fuses e.g. automatically adjusted itself or so and started to work at 1Mhz instead?

@Mikael Patel: Can you be more specific about measuring voltage and current? What to measure and compare to what and to find out what eventually? Thanks.

Fuses don't reset themselves. There also no failover in case the crystal isn't working. You could try reading the fuses to verify that they are set correctly.

@majenko that's the way we say it in my language. Appearantly it doesn't translate into English. Thanks for the heads up.

@Gerben It's also how a lot of native English speakers say it, despite it being completely incorrect

@Gerben: I can't get it. If I use same fuses for the other identical PCB design and it works just fine, why I would check the fuses again if they don't reset themselves? I am obviously missing a point here. Can you be more specific if you still insist for checking fuses? (which I will check anyway) Thank you.

Maybe something went wrong when you set the fuses, and so that they have their original value.

I am closing the case. It is not 100% satisfaction though. Because, using Visual Studio with Visual Micro didn't help me on that issue in a natural way but something else.
For the future reference for somebody might get benefit out of this, I like to explain here what I did to get over this issue briefly. As @Gerben (big credits go to him) has pointed the right direction, I did check fuses by installing Atmel Studio 7 and use its programmer.
Yes, the fuses were completely wrong. I have therefore read the fuses from my healthy PCB and noted aside and then applied these very same fuse settings to the slow working PCB. I have just programmed the fuses, Firmware was the one I programmed earlier in the uC. So, voilà, the slowness has gone.
I think I am going to use Atmel Studio 7 now on next to Visual Studio as it has everything built-in including Arduino support.
Thanks everybody involved.

Just burn the bootloader via  arduino ide before you burn your firmware. During bootloader burning, ide also configures the fuse bits you needed.

That's what I do. Then Upload Using Programmer to load without having the bootloader called.

I must agree with you guys. I do it at home with my hobby projects. The way I choose as stated in my solution has been already liked by the field engineers of ours. I can't ask them to use Arduino IDE to deploy new firmware versions. They used to use Atmel Studio flasher. Thanks anyway.


text:
Side by side two TFT LCDs 1.8'' with ST7735 driver but one acts differently
Hardware setup:

Custom PCB with ATMega 2560
Working Batch: TFT LCDs 1.8'' with ST7735 driver (Chinese version)
Bad Batch: TFT LCDs 1.8'' with ST7735 driver (Chinese version)

Library:
From Adafruit, latest version (1.7.0)
I've been using those LCDs for years. But, the LCDs I bought lately are not working as they should be.
They look completely identical from outside. I've bought from several different sellers from China just in case. All of them have the same behavior.
I therefore decided to find a software solution rather than trying out all LCDs in Chinese market.
Whatever variant of ST7735s I have (sellers claim they are just ST7735 nothing else), I need to adapt it to my software accordingly.
In order to keep the trial efforts efficient, I only test on the examples given by Adafruit until I proof it works. I share the outcome of the good and bad LCDs for your comparison below.
Any input greatly appreciated.

EDIT: A library had been sent by a seller. But, It doesn't look like it is 100% corresponding to ST7735. For example, since @Majenko asked, I add the initialization code from the library;
void Lcd_Init(void)
{

//调用一次这些函数，免得编译的时候提示警告
    LCD_CS =1;
    if(LCD_CS==0)
    {
       LCD_WR_REG_DATA(0,0);
       LCD_ShowString(0,0," ");
       LCD_ShowNum(0,0,0,0);
       LCD_Show2Num(0,0,0,0);
       LCD_DrawPoint_big(0,0);
       LCD_DrawRectangle(0,0,0,0);
       Draw_Circle(0,0,0);
     }

    LCD_REST=1;
    delayms(5);
    LCD_REST=0;
    delayms(5);
    LCD_REST=1;
    LCD_CS=1;
    delayms(5);
    LCD_CS =0;  //打开片选使能

        LCD_WR_REG(0x11); //Sleep out
    delayms(120); //Delay 120ms
    //------------------------------------ST7735S Frame Rate-----------------------------------------//
    LCD_WR_REG(0xB1);
    LCD_WR_DATA8(0x05);
    LCD_WR_DATA8(0x3C);
    LCD_WR_DATA8(0x3C);
    LCD_WR_REG(0xB2);
    LCD_WR_DATA8(0x05);
    LCD_WR_DATA8(0x3C);
    LCD_WR_DATA8(0x3C);
    LCD_WR_REG(0xB3);
    LCD_WR_DATA8(0x05);
    LCD_WR_DATA8(0x3C);
    LCD_WR_DATA8(0x3C);
    LCD_WR_DATA8(0x05);
    LCD_WR_DATA8(0x3C);
    LCD_WR_DATA8(0x3C);
    //------------------------------------End ST7735S Frame Rate-----------------------------------------//
    LCD_WR_REG(0xB4); //Dot inversion
    LCD_WR_DATA8(0x03);
    LCD_WR_REG(0xC0);
    LCD_WR_DATA8(0x28);
    LCD_WR_DATA8(0x08);
    LCD_WR_DATA8(0x04);
    LCD_WR_REG(0xC1);
    LCD_WR_DATA8(0XC0);
    LCD_WR_REG(0xC2);
    LCD_WR_DATA8(0x0D);
    LCD_WR_DATA8(0x00);
    LCD_WR_REG(0xC3);
    LCD_WR_DATA8(0x8D);
    LCD_WR_DATA8(0x2A);
    LCD_WR_REG(0xC4);
    LCD_WR_DATA8(0x8D);
    LCD_WR_DATA8(0xEE);
    //---------------------------------End ST7735S Power Sequence-------------------------------------//
    LCD_WR_REG(0xC5); //VCOM
    LCD_WR_DATA8(0x1A);
    LCD_WR_REG(0x36); //MX, MY, RGB mode
    LCD_WR_DATA8(0xC0);
    //------------------------------------ST7735S Gamma Sequence-----------------------------------------//
    LCD_WR_REG(0xE0);
    LCD_WR_DATA8(0x04);
    LCD_WR_DATA8(0x22);
    LCD_WR_DATA8(0x07);
    LCD_WR_DATA8(0x0A);
    LCD_WR_DATA8(0x2E);
    LCD_WR_DATA8(0x30);
    LCD_WR_DATA8(0x25);
    LCD_WR_DATA8(0x2A);
    LCD_WR_DATA8(0x28);
    LCD_WR_DATA8(0x26);
    LCD_WR_DATA8(0x2E);
    LCD_WR_DATA8(0x3A);
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0x01);
    LCD_WR_DATA8(0x03);
    LCD_WR_DATA8(0x13);
    LCD_WR_REG(0xE1);
    LCD_WR_DATA8(0x04);
    LCD_WR_DATA8(0x16);
    LCD_WR_DATA8(0x06);
    LCD_WR_DATA8(0x0D);
    LCD_WR_DATA8(0x2D);
    LCD_WR_DATA8(0x26);
    LCD_WR_DATA8(0x23);
    LCD_WR_DATA8(0x27);
    LCD_WR_DATA8(0x27);
    LCD_WR_DATA8(0x25);
    LCD_WR_DATA8(0x2D);
    LCD_WR_DATA8(0x3B);
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0x01);
    LCD_WR_DATA8(0x04);
    LCD_WR_DATA8(0x13);
    //------------------------------------End ST7735S Gamma Sequence-----------------------------------------//
    LCD_WR_REG(0x3A); //65k mode
    LCD_WR_DATA8(0x05);
    LCD_WR_REG(0x29); //Display on

}

They probably have different panels with different drive requirements.

@Majenko, yes, indeed. But which one? Million-dollar question. Sellers send me datasheet, drivers, etc. All point to ST7735.

Of they have sent you code you should compare the startup register settings against your existing code.

@Majenko, I did the comparison as you asked. There are similarities but differences as well. I also roughly compared to some other driver (ILI9341). I still couldn't recognize the driver. Maybe you may know. I edited my post and added that INIT code.  All library is a bit long so I didn't add here. If necessary I can. However, as you know that you can't trust the seller if they ever sent me the correct driver or they ever aware of what they sell.

The problem is that a TFT is made up of two parts: the controller chip, and the panel. The chip has to be configured by software to drive the panel in the right way. You can have the same chip on many different panels, and a library for one won't work right with another. I can check over the init code later on.

I think I see the difference. You have a library for the ST7735, but these new ones are in fact the ST7735S - a very different (though confusingly named) chip that needs a different library. Adafruit don't appear to have one, so you will have to find one by someone else.

@Majenko, I think so too. Either I will try to find one if exists (probably) or I will give a chance to the one given by the seller and try to convert it into Ardunio library. Thanks for the heads-up.

It's the init routine that needs replacing in the Adafruit library. It should be easy enough to port.

I replaced the INIT as per the code I mentioned in my post. But all I get a white background.

I've just ordered one on eBay from China. It'll take a few weeks to arrive....

As a backup plan, I've asked my Chinese PCB manufacturer to look for ST7735R versions locally. So, at least I might save the day while I am still working on an S version. I guess, you want to also make a library for everyone's sake, that would be great. I searched many resource centers like github. I am sure somebody already made one but many of them claim their library is for ST7735S but if you look at closely, it is still calling initR from Adafruit library. I guess, not many people aware of that S variant. Since that LCDs have no MISO (no read), you can't query the version of the LCD :(

I had asked my PCB manufacturer for looking bare display without back-plane a few days ago and told them that If they can find one and it works OK, I can design a back-plane for it and you make. Guess what, they found one. But strange thing is that the one they bought is -S version (claimed so) and they tested with my PBC and it worked. This is crazy. I am puzzled, I don't know what to say.

My supplier only does the -S version now (https://www.buydisplay.com/tft-display/tft-display-panel?cotroller_ic=883) so I guess the old non-S one has been discontinued. The -S variant is more capable anyway.

My TFT has just arrived. I'm going to spend today setting it up and getting it going. I'll report back later.

Ok, this is strange. Mine works straight out of the box. The PCB is a little different to yours, but it's supposedly an St7735S chip. Like yours it's a "green tab" variant panel, but I don't tell it to use the green tab init, just the default black tab, which works fine (the green tab init just adds an offset to the display).

You are lucky then. I didn't take my chance this time and I made a back-plane design and it is going to be manufactured next week for bare LCD. I purchased the bare LCDs. My fab will assemble them. At least that way I could also add some TVS for the SPI lines. Last time, during EMC tests the LCD was failed.

However, you said that Adafruit has not the ST7735S library. Have you made one yourself? If it is so, would you like to share for the Arduino community somewhere reachable?

No, it's just the stock adafruit library - when I started experimenting and looking at the examples I saw they have the .initR() function for selecting the variant: https://github.com/adafruit/Adafruit-ST7735-Library/blob/master/examples/graphicstest/graphicstest.ino#L87


text:
Possible to put the ESP8266 in bootloader mode without a FTDI?
I am trying to upload something directly to the ESP8266 using the ESP8266 IDE.
I have configured the ESP8266 to communicate at 9600 using UART_DEF and I have set the ESP8266 IDE at 9600. I see some tutorials that say to use a FTDI but I only have a Serial to TTL cable (note it even says at the bottom that it's not good for Arduinos :( ) and  am making the following connections:

ESP8266 RX - TTL cable TX
ESP8266 TX - TTL cable RX
ESP8266 GND - common GND
ESP8266 VCC - External 3.3V
GND from External 3.3V - common GND
ESP8266 GPI0 (through a 10k resistor) - common GND
ESP8266 GPI2 (through a 10k resistor) - External 3.3V
EPS8266 CH_PD - External 3.3V (sorry, that was wrong before)

However, when I upload that sketch I get an error that the board cannot be found. I have read online that the ESP has some bootloader mode that needs to be activated but haven't found great instructions on how to do that. Any advice would be appreciated.
FYI I also have an Uno if that is any help. I have communicated with the ESP8266 through the Uno before (connecting the Uno reset to ground) .

wire io 0 to gnd without resistor for the moment of esp8266 startup. esp8266 is put into flashing mode with io 0 LOW at startup. but the module can have a pull-up on io 0 to start normally.

AT firmware UART baud rate has nothing to do with bootloading baud rate. bootloader detects the baud rate

Connecting CH_PD to ground turns off the ESP8266.

The cable you point to is fine for programming the ESP8266. The only reason it's not "good" for an Arduino is the lack of a DTR signal to trigger a reset for you - which you can do manually anyway and still use it for an Arduino (if your reactions are fast enough).
You have no such problem with the ESP8266. Once you have it in bootloader mode it stays in bootloader mode until you tell it to exit bootloader mode.
First make sure that the ESP8266 is actually set up to run properly. That means:

Connect CH_PD to 3.3V, not GND, through a pull-up resistor.
Connect GPIO0 to 3.3V via a pull-up resistor.
Connect RST to 3.3V via a pull-up resistor.

Then for simplicity of programming:

Connect a button between RST and GND
Connect a button between GPIO0 and GND

To enter bootloader mode simply hold the GPIO0 button in, tap the RST button, then release the GPIO0 button.  When you have successfully uploaded your firmware just tap the RST button to exit bootloader mode.
ESP8266 boards with a built-in USB interface usually use both the DTR and the RTS pins to control both those buttons virtually. That's somewhat complex to arrange for an external USB to TTL UART adaptor, so it's simpler to just press the buttons manually.

Here's a link to a website that details the circuit and operation using an ESP-01 as an example.

the new esp-01S modules have a pull-up on io 0 and CH-PD wired to Vcc 'on board'

@Juraj Indeed they do - however the OP never mentioned which ESP8266 module (if any) they are using.

Wow this is a great start! It's still not working for me. I am using a lower resistor on the CH_PD and GPIO2 - VCC connection (500 Ohms) could that be a reason? Here is a picture of my setup if that's any help...https://imgur.com/a/miZuQN9

It's no help at all. All I see is a bundle of meaningless wires. Not even an ESP8266 in there. What module are you using?

According to this site, I think I have ESP8266-01 but I am not really sure how to check just from looking at it. https://www.esp8266.com/wiki/doku.php?id=esp8266-module-family

The ESP-01 is the plugin module with the 2x4 pins on one end. That's what you have, correct?

Grab yourself one of these: https://www.ebay.co.uk/itm/322466871464 - or something similar. Make sure it's one with the switch on it for switching between programming and normal running mode.

Yes, I have the 2x4 pins. So it's not possible to program the ESP8266-01 without one of those?

It is possible - as long as you follow the instructions properly. That adaptor just makes things a lot easier - no wires to mess with. I have three of them ;)

Yeah, I still haven't been able to get it to work. The closest I got was by doing everything you wrote up above but unplugging GPIO2, then at least it starts uploading and says Writing at 0x00000000... (8 %)Traceback (most recent call last):..but then I get 'File "C:/Users/nickc/AppData/Local/Arduino15/packages/esp8266/hardware/esp8266/2.5.2/tools/pyserial\serial\serialwin32.py", line 323, in write
raise writeTimeoutError'

Update: miracle of miracles, it works! Thanks for your help. What I had to do was 1) unpower/repower the ESP8266 before going through the bootload sequence and 2) set the IDE BUILTIN LED to pin 1, then it worked!


text:
Error sending data from ESP8266 to Uno
I am sending data from an ESP8266 to an Uno (I need to use the Uno because it has more inputs than the ESP and I need those for my project.) The ESP8266 is connected to the Uno's Serial pins 0/1 RX/TX (communicating on BAUD rate of 9600), and then I have a SoftwareSerial out from the Uno (on a BAUD rate of 57600) for debugging. Something weird is happening though. The transfer works a couple times and then I get this in the log:
--------------- CUT HERE FOR EXCEPTION DECODER ---------------

Exception (0):
epc1=0x40239ba1 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000

>>>stack>>>

ctx: sys
sp: 3fffebd0 end: 3fffffb0 offset: 0190
3fffed60:  40239b2e 3feffe00 3fffd9d0 00000050
3fffed70:  000005e0 00000000 40103501 3ffed4d0
3fffed80:  0000003c 00000000 00000022 401049e6
3fffed90:  401049c8 3fffc100 3ffef2a0 00000000
3fffeda0:  00000000 4022279f 00000020 40100198
3fffedb0:  400005e1 150cc636 00000005 4010144c
3fffedc0:  4022279f 00000030 00000010 3ffefdcc
3fffedd0:  40221007 3fff051a 00000014 00000000
3fffede0:  00000000 00000061 00000061 00000001
3fffedf0:  3ffecdb8 00000006 00000000 3fff04fc
3fffee00:  3fff051a 3ffef2a0 00000061 00000000
3fffee10:  3ffe9be8 7fffffff 50800000 00000001
3fffee20:  00000001 00004a08 00000142 401006d7

Any ideas what could be causing this? Here is the code that the Uno uses for receiving from the ESP and printing to the SoftwareSerial (Serial is the RX/TX and mySerial is the SoftwareSerial). It uses a couple helper functions I haven't included here but let me know if you need them:
void receiveFromESP() {
  if (Serial.available() > 0   ) {
    endofTransmission == 0;
    alreadyZeroed = 0 ;
    receivedChar = Serial.read();
    mySerial.print(receivedChar);
    if (receivedChar == '[' ) {
      lastNum = 0 ;
      commaNumber = 0 ;
      lastWasNum = 0 ;
    }
    if (receivedChar == '*' ) {
      lastNum = 0 ;
      commaNumber = 0 ;
      lastWasNum = 0 ;
      createArray[0] = 4;
      createArray[1] = 4;
      createArray[2] = 4;
      createArray[3] = 4;
    }
    if (receivedChar == 'A'
        || receivedChar == 'B'
        || receivedChar == 'C'
        || receivedChar == 'D'
        || receivedChar == 'E'
        || receivedChar == 'F'
        || receivedChar == 'G'
        || receivedChar == 'H'
        || receivedChar == 'I'
        || receivedChar == 'J'
        || receivedChar == ','
       ) {
      if (lastWasNum == 1) {
        createArray[commaNumber] = lastNum;
        commaNumber++;
      }
      lastWasNum = 0 ;
      createArray[commaNumber] = charToNumber(receivedChar);
      commaNumber++;
      lastNum = 0 ;
    }
    if (receivedChar == ']') {
      lastWasNum = 0 ;
      endofTransmission = 1 ;
      for (int i = 0; i < 50; i++) {
        mySerial.print(createArray[i]);
        mySerial.print(':');
      }
    }
    if (
      receivedChar == '0'
      ||  receivedChar == '1'
      ||  receivedChar == '2'
      ||  receivedChar == '3'
      ||  receivedChar == '4'
      ||  receivedChar == '5'
      ||  receivedChar == '6'
      ||  receivedChar == '7'
      ||  receivedChar == '8'
      ||  receivedChar == '9'
    ) {
      lastWasNum = 1;
      receivedCharInt = (int)receivedChar - 48;
      lastNum = lastNum * 10 + receivedCharInt;
    }
    t = millis();
  }
};

As requested, here is the full ESP code:
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>

#include <DNSServer.h>            //Local DNS Server used for redirecting all requests to the configuration portal
#include <ESP8266WebServer.h>     //Local WebServer used to serve the configuration portal
#include <WiFiManager.h>          //https://github.com/tzapu/WiFiManager WiFi Configuration Magic

#define SERIAL_BUFFER_SIZE 256

void setup() {

  Serial.begin(9600);
  for (uint8_t t = 4; t > 0; t--) {
    Serial.printf("*WIFISETUP] WAIT %d...\n", t);
    Serial.flush();
    delay(1000);
  }
  WiFiManager wifiManager;
  wifiManager.setConfigPortalTimeout(120);
  //first parameter is name of access point, second is the password
  wifiManager.autoConnect("AP-NAME", "AP-PASSWORD");
}

void loop() {
    WiFiClient client;
    HTTPClient http;
    if (http.begin(client, "[URL]")) {  // HTTP
      // start connection and send HTTP header
      http.addHeader("Content-Type", "text/plain");
      http.addHeader("Authorization", "Basic dXNlcm5hbWU6cGFzc3dvcmQ=");
      int httpCode = http.GET();

      if (httpCode == 200 ) {  // HTTP header has been sent and Server response header has been handled
        // file found at server
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          String payload = http.getString();
          Serial.println(payload);
        }
      } else{
        if (httpCode > 0 ){
          //website problem
          Serial.printf("[2,1,1,1]");
        }
        if (httpCode == -1 ){
          //wifi problem
          Serial.printf("[4,1,1,1]");
          ESP.reset();
        }
      }
      http.end();
    } else {
      Serial.printf("[HTTP} Unable to connect\n");
    }
  delay(10000);
}

use stack decoder IDE plugin to decode the stack. the crash is in esp code, so Uno code is not what we need to see

Thanks, I am looking into the stack decoder IDE plugin now. To be clear, I am seeing this on the SoftwareSerial log coming out of the Uno. Can I ask how you know the crash is in esp code? Thanks

I've seen it many times. Uno doesn't produce a stack dump and the "CUT HERE ..." is a joke by esp8266 arduino developers

I am connecting just the ESP to my computer to watch the log. The ESP sends data every 30 seconds so I assume I will see the crash happening there too and will check out the stack decoder IDE plugin too. (The ESP is sending on 9600 and the SoftwareSerial is on 57600.)

"The ESP is sending on 9600 and the SoftwareSerial is on 57600." ???

I added clarification about the BAUD rates to the question text.

Post your ESP code, you are likely has a buffer overflow somewhere in your ESP. BTW, use if (receivedChar >= '0' && receivedChar <='9')  would be much simpler for your Arduino code.

I added the ESP code

Why not use a PCF8574 I2C expansion board, they work great on 3V3. If you need more inputs or outputs use the PCF8575. There are a lot of I2C expansion boards you can select from. They will also be faster and less convoluted then your existing solution.

The answer to "why not" is "I have never heard of I2C boards before." Please forgive my lack of knowledge, and my convoluted solutions, as I am new to this. I would appreciate your help in addressing the problem that I took time to lay out in this post. Thank you.

Try going to ebay and search for "I2C modules"  I got over 7,000 hits.  The exception you are getting is from the ESP8266. Eliminate the Delay() and your crashing should go away. There are lots of posts on the web telling you why not to use it. By the way you did not clearly lay out your problem you just posted a lot of code. I googled ESP8266 Exception (0): and got this as the first hit: https://www.espressif.com/sites/default/files/documentation/esp8266_reset_causes_and_common_fatal_exception_causes_en.pdf

I have reconfigured the code to use millis() instead of delay(). I am still facing the same error message. Please let me know if there are problems I could explain better in my post - I am trying to be helpful and provide all the information that I can.

How about showing a schematic. Be sure to show the ground connections as you have them connected. You might go into a little more detail about the baud rates and how do you get the serial debugger to work with softwareserial.