text:
Can the Arduino-HomeKit-ESP8266 library be used with the WiFi101 library?
I am currently trying to create a project to setup a HomeKit remote control to control my smart home devices with the Arduino-HomeKit-ESP8266 library.
I am currently using a Arduino-based TinyCircuit device with the Atmel ATWINC1500 WiFi module. Is there any solutions available or any way to modify the code to make it work with my current WiFi shield, as it uses the WiFi101 library instead of the WiFi library?
I am trying to test the "ConnectWithWPA.ino" from the WiFi101 examples with the HomeKit library. The code requires a "pgmspace.h" which I am not too sure what is it for.
ConnectWithWPA.ino:
/*

 This example connects to an unencrypted WiFi network.
 Then it prints the  MAC address of the WiFi shield,
 the IP address obtained, and other network details.

 Circuit:
 * WiFi shield attached

 created 13 July 2010
 by dlf (Metodo2 srl)
 modified 31 May 2012
 by Tom Igoe
 */
#include <SPI.h>
#include <WiFi101.h>
#include <arduino_homekit_server.h> // INSERTED CODE

//access the config defined in C code
#include "arduino_secrets.h"
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID;        // your network SSID (name)
char pass[] = SECRET_PASS;    // your network password (use for WPA, or use as key for WEP)
int status = WL_IDLE_STATUS;     // the WiFi radio's status

extern "C" homekit_server_config_t config; // INSERTED CODE

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    // don't continue:
    while (true);
  }

  // attempt to connect to WiFi network:
  while ( status != WL_CONNECTED) {
    Serial.print("Attempting to connect to WPA SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network:
    status = WiFi.begin(ssid, pass);

    // wait 10 seconds for connection:
    delay(10000);
  }

  // you're connected now, so print out the data:
  Serial.print("You're connected to the network");
  printCurrentNet();
  printWiFiData();

  arduino_homekit_setup(&config); // INSERTED CODE
}

void loop() {
  // check the network connection once every 10 seconds:
  delay(10000);
  printCurrentNet();

  arduino_homekit_loop(); // INSERTED CODE
}

void printWiFiData() {
  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP A'ddress: ");
  Serial.println(ip);
  Serial.println(ip);

  // print your MAC address:
  byte mac[6];
  WiFi.macAddress(mac);
  Serial.print("MAC address: ");
  printMacAddress(mac);

}

void printCurrentNet() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print the MAC address of the router you're attached to:
  byte bssid[6];
  WiFi.BSSID(bssid);
  Serial.print("BSSID: ");
  printMacAddress(bssid);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.println(rssi);

  // print the encryption type:
  byte encryption = WiFi.encryptionType();
  Serial.print("Encryption Type:");
  Serial.println(encryption, HEX);
  Serial.println();
}

void printMacAddress(byte mac[]) {
  for (int i = 5; i >= 0; i--) {
    if (mac[i] < 16) {
      Serial.print("0");
    }
    Serial.print(mac[i], HEX);
    if (i > 0) {
      Serial.print(":");
    }
  }
  Serial.println();
}

It produced this error when verifying:
Alternatives for osapi.h: []
ResolveLibrary(osapi.h)
  -> candidates: []
In file included from libraries\HomeKit-ESP8266\src/wolfssl/wolfcrypt/settings.h:171:0,
from \libraries\HomeKit-ESP8266\src/wolfssl/wolfcrypt/types.h:27,
from \libraries\HomeKit-ESP8266\src/wolfssl/wolfcrypt/ed25519.h:26,
from \libraries\HomeKit-ESP8266\src/crypto.h:12,
from \libraries\HomeKit-ESP8266\src/arduino_homekit_server.h:15,
from \ConnectWithWPA.ino:17:
\libraries\HomeKit-ESP8266\src/user_settings.h:15:10: fatal error: osapi.h: No such file or directory
 #include "osapi.h"
          ^~~~~~~~~
compilation terminated.

After adding osapi.h into the HomeKit src folder.
Alternatives for user_config.h: []
ResolveLibrary(user_config.h)
  -> candidates: []
In file included from \libraries\HomeKit-ESP8266\src/user_settings.h:15:0,
                 from \libraries\HomeKit-ESP8266\src/wolfssl/wolfcrypt/settings.h:171,
                 from \libraries\HomeKit-ESP8266\src/wolfssl/wolfcrypt/types.h:27,
                 from \libraries\HomeKit-ESP8266\src/wolfssl/wolfcrypt/ed25519.h:26,
                 from \libraries\HomeKit-ESP8266\src/crypto.h:12,
                 from \libraries\HomeKit-ESP8266\src/arduino_homekit_server.h:15,
                 from \ConnectWithWPA.ino:17:

\libraries\HomeKit-ESP8266\src/osapi.h:29:10: fatal error: user_config.h: No such file or directory
 #include "user_config.h"
          ^~~~~~~~~~~~~~~
compilation terminated.

After adding one example of user_config.h into the HomeKit src folder.
Alternatives for pgmspace.h: []
ResolveLibrary(pgmspace.h)
  -> candidates: []
In file included from \libraries\HomeKit-ESP8266\src/homekit_debug.h:12:0,
                 from \libraries\HomeKit-ESP8266\src/user_settings.h:16,
                 from \libraries\HomeKit-ESP8266\src/wolfssl/wolfcrypt/settings.h:171,
                 from \libraries\HomeKit-ESP8266\src/wolfssl/wolfcrypt/types.h:27,
                 from \libraries\HomeKit-ESP8266\src/wolfssl/wolfcrypt/ed25519.h:26,
                 from \libraries\HomeKit-ESP8266\src/crypto.h:12,
                 from \libraries\HomeKit-ESP8266\src/arduino_homekit_server.h:15,
                 from \ConnectWithWPA.ino:17:
\libraries\HomeKit-ESP8266\src/esp_xpgm.h:15:10: fatal error: pgmspace.h: No such file or directory
 #include <pgmspace.h>
          ^~~~~~~~~~~~
compilation terminated.

My TinyCircuit uses these components:

TINYZERO PROCESSOR BOARD
TINYSCREEN OLED TINYSHIELD
WIFI TINYSHIELD (ATWINC1500)
Lithium Ion Polymer battery - 3.7V 150MAH

you can't use it.


text:
Controlling DC motor with joystick using Arduino
I am working on modifying code to control two DC motors with a joystick using Arduino. The code I have works, but the motor accelerates very rapidly and is difficult to control. I would appreciate any help or pointers to get the motor under control. Here is the code I have so far:
const int ledPin = 3; //Led to Arduino pin 3 (PWM)

//Variables
bool started= false;//True: Message is started
bool ended  = false;//True: Message is finished
char incomingByte ; //Variable to store the incoming byte
char msg[3];    //Message - array from 0 to 2 (3 Drive_Analog_Values -PWM - e.g. 240)
byte index;     //Index of array
bool started1= false;//True: Message is started
bool ended1  = false;//True: Message is finished
char msg1[3];    //Message - array from 0 to 2 (3 Drive_Analog_Values - PWM - e.g. 240)
byte index1;     //Index of array
bool started2= false;//True: Message is started
bool ended2  = false;//True: Message is finished
char msg2;
bool started3= false;//True: Message is started
bool ended3  = false;//True: Message is finished
char msg3;
int Fwd_Drive = 0;
int Rev_Drive = 0;
int Left_Turn = 0;
int Right_Turn = 0;
char Dump = '0';
char Retract = '0';

void setup() {

//setup interrupts
cli();//stop interrupts

//set timer1 interrupt at 1Hz
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;//initialize counter value to 0
  // set compare match register for 1hz increments
  OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536)
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS10 and CS12 bits for 1024 prescaler
  TCCR1B |= (1 << CS12) | (1 << CS10);
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);

 sei();//allow interrupts

  //Start the serial communication
  Serial.begin(9600); //Baud rate must be the same as is on xBee module
  pinMode(ledPin, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
}

ISR(TIMER1_COMPA_vect){ //timer1 turns off all values every 1 second
   analogWrite(5, 0);
   analogWrite(6, 0);
   analogWrite(9, 0);
   analogWrite(10, 0);
   digitalWrite(2,LOW);
   digitalWrite(4,LOW);
}

void loop() {
  //digitalWrite(13, LOW); //Debug LED
  while (Serial.available()>0){
        //Read the incoming byte
        incomingByte = Serial.read();
        //digitalWrite(13, HIGH);//Debug LED
        //Start the message when the '<' symbol is received
        if(incomingByte == '<'){
            started = true;
            index = 0;
            msg[index] = '\0'; // Throw away any incomplete packet
        }

        //End the message when the '>' symbol is received
        else if(incomingByte == '>'){
            ended = true;
            break; // Done reading - exit from while loop!
        }
        //Read the message!
        else{
            if(index < 4){ // Make sure there is room
                msg[index] = incomingByte; // Add char to array
                index++;
                msg[index] = '\0'; // Add NULL to end
            }
        }

        if(incomingByte == '['){
            started2 = true;
            msg2 = '\0';
        }
        else if(incomingByte == ']'){
            ended2 = true;
            break; // Done reading - exit from while loop!
        }
        //Read the message!
        else{
            msg2 = incomingByte;
        }
      if(incomingByte == '{'){
            started3 = true;
            msg3 = '\0';
        }
        else if(incomingByte == '}'){
            ended3 = true;
            break; // Done reading - exit from while loop!
        }
        else{
            msg3 = incomingByte;
        }
    }

 if(started && ended){//Driving Logic
        int Drive_Analog_Value = atoi(msg);
        //analogWrite(ledPin, Drive_Analog_Value);//Only for debugging
        //Serial.println(Drive_Analog_Value); //Only for debugging
        if(Drive_Analog_Value>130){
            Rev_Drive = 0;
            Fwd_Drive = map(Drive_Analog_Value, 131, 255, 0, 70);
        }
        else if(Drive_Analog_Value<124){
            Fwd_Drive = 0;
            Rev_Drive = map(Drive_Analog_Value, 0, 123, 70, 0);
        }
        else{
            Fwd_Drive = 0;
            Rev_Drive = 0;
        }
        analogWrite(5, Fwd_Drive);
        analogWrite(6, Rev_Drive);
        index = 0;
        msg[index] = '\0';
        started = false;
        ended = false;
}

that cannot be all of your code ... it does not compile

please format your code properly the if, else if and else should be at the same indent level

Have you tried outputting the drive numbers (like Fwd_Drive) to Serial and look if they look correct?

The numbers aren't  correct.  They are way higher than they should be.  Would it be as simple as changing the mapping values?

source: Stack Exchange

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

sort: votes


text:
multiple blinking LEDs at different intervals, morse code A included
Good evening,
I am writing Arduino code to flash multiple LEDS at different sequences from different pins. Everything is working well, however I cant determine how to add in a Morse Code A flash sequence.
Ideally the sequence would go 1s, on 1s off, 3s on, 3s off. then repeat continuously, this would be for a MO (A) bouy
Below is the format I have used for all other lights and works well with 8 different sequences.
// A is 1s, B is 2.5s, C is 4s, D is 5s, F is 6s, G is 8s, H is 10s ,

#define aLed 2
#define bLed 3
#define cLed 4
#define dLed 5
#define fLed 6
#define gLed 7
#define hLed 8

void setup() {
  pinMode(aLed, OUTPUT); //pin2 Output
  pinMode(bLed, OUTPUT); //pin3 Output
  pinMode(cLed, OUTPUT); //pin4 Output
  pinMode(dLed, OUTPUT); //pin5 Output
  pinMode(fLed, OUTPUT); //pin6 Output
  pinMode(gLed, OUTPUT); //pin7 Output
  pinMode(hLed, OUTPUT); //pin8 Output

}

void loop() {
  BlinkA(1000);
  BlinkB(2500);
  BlinkC(4000);
  BlinkD(5000);
  BlinkF(6000);
  BlinkG(8000);
  BlinkH(10000);

}
 void BlinkA (int interval){
   static long prevMill = 0;
   if ((millis() - prevMill) >= interval){
    prevMill = millis();
    digitalWrite(aLed, !digitalRead(aLed));
 }
}
void BlinkB (int interval){
   static long prevMill = 0;
   if (((long)millis() - prevMill) >= interval){
    prevMill = millis();
    digitalWrite(bLed, !digitalRead(bLed));
  }
 }
  void BlinkC (int interval){
   static long prevMill = 0;
   if ((millis() - prevMill) >= interval){
    prevMill = millis();
    digitalWrite(cLed, !digitalRead(cLed));
 }
}
 void BlinkD (int interval){
   static long prevMill = 0;
   if ((millis() - prevMill) >= interval){
    prevMill = millis();
    digitalWrite(dLed, !digitalRead(dLed));
 }
}
 void BlinkF (int interval){
   static long prevMill = 0;
   if ((millis() - prevMill) >= interval){
    prevMill = millis();
    digitalWrite(fLed, !digitalRead(fLed));
 }
}
 void BlinkG (int interval){
   static long prevMill = 0;
   if ((millis() - prevMill) >= interval){
    prevMill = millis();
    digitalWrite(gLed, !digitalRead(gLed));
 }
}
 void BlinkH (int interval){
   static long prevMill = 0;
   if ((millis() - prevMill) >= interval){
    prevMill = millis();
    digitalWrite(hLed, !digitalRead(hLed));
 }
}

to format the code listing, put ~~~ on a blank line before the code ... and same on a blank line after the code

what is your question?

Would this answer be helpful? https://arduino.stackexchange.com/a/48588/37523

Re “1s on, 1s off, 3s on, 3s off”: That would be keying at 1.2 words per minute! Nobody, not even a complete beginner, goes that slow. If you want someone to be able to read the “A” before they get bored, you should not go below ≈ 5 WPM (240 ms on, 240 ms off, 720 ms on, 720 ms off).

@EdgarBonet Unless he wants to simulate the blinking of a lighthouse. They might go this slow and occassionally use morse code patterns.

https://github.com/MajenkoLibraries/Blinker

https://github.com/MajenkoLibraries/MorseStatus

multiple blinking LEDs at different intervals, (not all periodic)...

I changed your question hopefully with out changing its meaning.
Based on this question, I would suggest using a finite state machine.  Assuming you are using differently named "BlankI()" functions for each LED, consider adding state machine features to 1 of these functions to control the "not periodic" LED.  Consider a state machine with 4 state one for each action:

LED On for 1 second.
LED Off for 1 second.
LED On for 3 seconds.
LED Off for 3 seconds.

Use a counter (either global or static to preserve its value between calls to that function) to track the states.  Use a switch/case coding pattern to set the "prevMill" to the appropriate time delay for the current state.

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


text:
I am trying to connect ps3 controller to Arduino mega using usb host shield, but it isn't getting?
I tried various method from YouTube and also debugged it. It shows that ps3 controller address was set to local Bluetooth address, after that when I try to connect, it shows that it is receiving request from controller but however the request isn't getting completed
PS3 Bluetooth Library Started
PS3 Bluetooth Library Started
Bluetooth Dongle Initialized
HCI Reset complete
Write class of device
Local Bluetooth Address: 00:1A:7D:DA:71:10
Wait For Incoming Connection Request
Incoming Connection Request
Remote Name: Pro Controller
Connection Failed: 08
Connection Failed: 08
Connection Failed: 08
Connection Failed: 08
Connection Failed: 08
Wait For Incoming Connection Request
HCI Disconnected from Device
Wait For Incoming Connection Request
Connection Failed: 13
Connection Failed: 13

when I try to reset ps3 controller address, it shows that address was reset.
PS3 Bluetooth Library Started
Bluetooth Dongle Initialized
HCI Reset complete
Write class of device
Local Bluetooth Address: 00:1A:7D:DA:71:10
Wait For Incoming Connection Request
PS3 Bluetooth Library Started
PS3 Bluetooth Library Started
Bluetooth Dongle Initialized
HCI Reset complete
Write class of device
Local Bluetooth Address: 00:1A:7D:DA:71:10
Wait For Incoming Connection Request
setAddr: 0E
BTD Init Failed, error code: 0E

Dualshock 3 Controller Connected
Bluetooth Address was set to: 00:1A:7D:DA:71:10
Bluetooth Dongle Initialized
HCI Reset complete
Write class of device
Local Bluetooth Address: 00:1A:7D:DA:71:10
Wait For Incoming Connection Request
PS3 Bluetooth Library Started
PS3 Bluetooth Library Started
Bluetooth Dongle Initialized
HCI Reset complete
Write class of device
Local Bluetooth Address: 00:1A:7D:DA:71:10
Wait For Incoming Connection Request
Incoming Connection Request
Remote Name: Pro Controller
Connection Failed: 08
Connection Failed: 08

yes I am trying to connect a ps3 controller only @jsotola. also I have one  old ps3 controller which is getting connected but this one doesn't. can you please suggest something. I am in desperate need of it

@jsotola sorry my mistake, I have made the changes in the question and now it says that I am trying to connect ps3 controller. thank you for suggesting changes. also please do suggest something. thanks

search for arduino ps3 controller


text:
Rotary encoder weird values
I am trying to understand this rotary encoder I have, but it makes no sense to me.
I am using this rotary encoder:
https://www.amazon.com/gp/product/B07DM2YMT4/
CYT1100 aka CY110 aka EC11
I am using this wiring:
https://i.sstatic.net/aMyR5.png
P2 is the "push button" and it gives continuity when pressed.
I am using a knock off arduino nano and this is my simple script:
#define PIN_CLK 2

void setup()
{
    Serial.begin(9600);
    pinMode(PIN_CLK, INPUT);
}

void loop()
{
    auto val = digitalRead(PIN_CLK);

    Serial.println("CLK:" + String(val));
}

Where PIN_CLK is connected to A (DW) or B (CLK) in the diagram.
My expectation is that A and B should be either a constant HIGH or LOW depending on where the brushes are internally. Not switching to HIGH or LOW for a moment and then returning to what it was before.
When I check them with my multimeter, they are both always 5v (when its not making loose contact on the breadboard).
The serial plotter says its switching between HIGH and LOW repeated:
https://i.sstatic.net/6VC3z.png
Same with the Serial monitor:
https://i.sstatic.net/wAk0v.png
When I spin the encoder, it gives me gaps of LOW in the output like this:
https://i.sstatic.net/lOUmx.png
If I hold my index and thumb against P1 (5v) and A (CLK) while spinning the encoder. I get constant stream of HIGH with a LOW on every notch spin:
https://i.sstatic.net/CzUwV.png
Can someone explain this behavior and how this encoder is suppose to work?
Edit: I tried this schematic:
https://i.sstatic.net/Mlj1l.png
Whenever I turn the encoder. The LED blinks for a few milliseconds. Then turns off.
Is it suppose to stay solid depending on the 2 bit states?
Edit2: If I turn it extremely slowly. It turns the leds on in the order of left right or right left depending on the direction.
So the led diagram above works, but its weird to me.

P1 and P2 is probably the switch ... connect one to GND and the other to IO pin ... enable the pullup resistor on the IO pin ... do the same with B and A ... do not connect any pins to 5 V

@jsotola I disconnected P1 from 5V and connected G to ground, A to D2, B to D3. The values jitter between HIGH and LOW. Then both go low for a few ticks when spinning the encoder. Same result as before.

did you enable the pullup resistors?

@jsotola I did now

This is just quadrature encoding / decoding. There are tutorial all over the internet for this.  It's how old mice work.  Followup on this comment if you need to know more and I'll create another answer based on this approach.

There are several problems happening here. Since your code only covers one input pin, I'm going to talk about input A. This pin is left floating! When you turn the dial, the brush connects A and/or B to G in your photo, or in other words, pins A/B to ground. But if A/B is not connected to ground, there is no other voltage state - it's just left floating. You need to have a logic LOW 0V and a logic HIGH (either 3.3V or 5V depending on your Arduino board) for the Arduino to be able to distinguish between the LOW and HIGH states. You can solve this by changing your code to:
pinMode(PIN_CLK, INPUT_PULLUP);

This way when the pin (A) is not connected to GND via (G), it is held at a logic HIGH state.
P1 & P2 are the for the button, so you can't ignore one of the pins. To wire that correctly using an input pullup, P1 needs to connect to GND. P2 needs to connect to an input pin with another input_pullup. When the button is unpressed, the state will default to HIGH. When it's pressed, it will be connected to GND and show as LOW.
You are most likely following the images online for wiring the encoders that are already on a PCB. That PCB has 3 pullup resistors on it. Regardless if you are using code to do it or hardware, the circuit needs to look like this. input_pullup on the Arduino will act just like resistors shown in the circuit.
Here is a great resource: https://lastminuteengineers.com/rotary-encoder-arduino-tutorial/

I got it working after I used the LED example to realize that the current is only flowing in between notches and not all the time. The pull up requirement was also something that I was missing. The only difference between yours and mine is that I'm not connecting the 5v at all. I do have some more questions if you can answer them. For CLK and DT. Why use two resistors on the signal paths instead of just 1 resistor on the ground path? That seems to work ok so far. Also, are resistors even needed if connecting a arduino pin to ground?

If you combined resistors both CLK & DT would go LOW at the same time, which means you won't be able to use the encoder properly, if you are trying to do CW and CCW. You should really look up an Arduino button tutorial and get familiar with what input pullup/pulldown resistors do, that will answer all your questions.

It doesn't look like this encoder ever has both CLK and DT on at the same time. If I try to edge it. It flickers between them, but they're never both on. Edit: I tested it and both single resistor and double resistor ended up having double LOW readings when rotating the encoder.

Spend some time reading that tutorial I linked :)

When encountering weird values from a rotary encoder, there are a few possible reasons and troubleshooting steps you can take:
Mechanical issues: Check if there is any physical damage or obstruction affecting the rotary encoder's movement. Ensure that it rotates smoothly without any unusual resistance or skips.
Loose connections: Verify the wiring connections between the rotary encoder and the device it is connected to. Ensure that the connections are secure and properly seated.
Electrical noise: Electrical noise or interference can sometimes cause erratic readings. Try using shielded cables for the connections and consider adding capacitors or ferrite beads to filter out noise.
Incorrect configuration: Review the setup and configuration of the rotary encoder in your code or software. Make sure that you have selected the correct type of encoder (incremental or absolute) and that the signal processing is correctly implemented.
Debouncing: If you are using an incremental rotary encoder, it may produce multiple pulses or bouncing signals when rotating. Implementing debouncing techniques in your code can help filter out these erroneous readings.
Resolution and speed settings: Check if the resolution and speed settings in your code or software match the specifications of your rotary encoder. Incorrect settings can lead to unexpected values.
Compatibility issues: Ensure that the rotary encoder you are using is compatible with the device or system you are connecting it to. Check the specifications and requirements of both the encoder and the device to ensure compatibility.
If you have gone through these troubleshooting steps and are still experiencing weird values from your rotary encoder, it might be worth considering a replacement or consulting the manufacturer's support for further assistance.


text:
Switching fan on with transistor, fan running very slowly
I want to control a fan with an arduino from 0 rpm to full rpm. Using a (modified) pwm signal from the arduino I can control the speed w/ the pwm signal, but it cannot go all the way to 0 rpm.
So I decided to add a transistor as a switch using following schematic.

The fan is a Snowman F120, I used BC337 as a transistor (800mA) and a resistor of 2.2 kOhm, for controller I use pin 6 on an arduino nano and set it high/low. Arduino and the fan are both run from the 12v power supply. I removed the pwm signal to just have it full on or off for testing purposes.
I was hoping to use the transistor as an on/off switch and when on just send the pwm signal as that was working already.
The fan can now be turned off/on with the arduino but it spins super slow, say 10% of full pwr. Can someone explain why this is? Is there a better way to control this?
Edit: I did try to remove the resistor completely and the fan still moves only slowly
Edit: it is a 4 wire fan, but it cannot go all the way to 0 with pwm. That's why I want the 'switch'
I lowered the resistor to 120 ohm, and switched gpio pin, no effect, if I wait long enough the transistor gets hot
Edit: I connected the transitor to the 5V of the Arduino instead of the Digital out (high) and low and behold fan works well (resistor still in between, both 120 and 2.2kOhm tested, both situations work). I guess the digital output cannot provide enough current?
**
Solution:

Used IRLZ34N mosfet with a 120Ohm as gate resistor
and a 100 kOhm as pull down resistor to GND as otherwise the mosfet would always be open
**

Is that a 4-wire fan?

With a 2.2K resistor you're massively limiting the current that can flow through the transistor.
I haven't looked up the specs on that transistor, but taking typical values for Vbe (0.6V) and Hfe (100) we can calculate:
Ibe = (5V - 0.6V) / 2200 ohm = 0.002A

Ice = Ibe x Hfe = 0.002 x 100 = 0.2A

So even though your transistor is capable of 800mA you're actually only allowing 200mA maximum.
Add to that the voltage drop of the transistor and you have a recipe for a slow fan.
Really you would be better off using an N-channel MOSFET for this job since it is controlled by the voltage at the gate, not the current flowing through it. Also in saturation mode they are more like a very low value resistor rather than a couple of diodes.
Also if your fan is a 4-wire fan (as the ones I have found on Google looking for that model are) then you don't even want a transistor: one of the pins of the fan is a PWM input which you can connect (along with fan ground) direct to the Arduino (it basically includes the transistor internal to the fan) for speed control.

The BC337 has relatively high DC gain. 4-pin fans often can not be dimmed-to-off with PWM, I guess that's why the OP wants to use the transistor.

@SimSon Every 4 pin fan I've ever used has stopped at 0% duty cycle...  That's how you achieve silent computing.

I did try to change the resitor to a low value 120 Ohm, but that did not change the outcome.
it is a 4wire fan, but it does not stop at 0% duty cycle. I was surprised too but apparently it's not that uncommen. Instead of buying new fans I decided I would add a transistor as a switch

I'm fine to switch to a mosfet, but don't have any laying around. Do you have a suggestion which one to use? Could I use it as a drop-in replacement in the same circuit?

This guy perhaps, IRLZ34N?
https://eu.mouser.com/ProductDetail/Infineon/IRLZ34N?qs=sGAEpiMZZMua%252Bgb89%252BTvM2aBJqYrAlCZ6Q%252BoLUS32zE=

That one would work fine.

Type A fans as specified by Intel do not stop at 0% duty cycle, only Type B & C do...

I ordered a couple, will be about a week until I can test.

I have used the BC337 to switch small loads like fans, so I know this works in general. As Majenko explained, 2.2kOhm base resistance is a bit high, though.
"I did try to remove the resistor completely and the fan still moves only slowly" - if you controlled the transistor without base resistor, chances are that the GPIO got damaged, try another GPIO with 500-1000 Ohm.
As a rule of thumb: If the transistor gets warm when switching a small load, something is wrong. If there's a reasonable voltage drop between emitter and collector, reduce the base resistance if possible.
Another thing is that you should not low-side-switch a 4-pin fan if you want to control it with its PWM input at the same time. In case the ground path is disconnected, the entire fan's circuit is at supply voltage level: Arduino will see 12V at its pins. Use a high-side switch instead
Edit: did you actually make sure that the fan had 100% duty cycle at the PWM input when the transistor was on?

the transistor did get hot after a some time say 20-30s. I also lowered the resistor to 120 Ohm with no effect, still gets hot. Then I changed from the Digital out to just the 5V and tested with both resistors, both seem to make the fan go full speed with the pwm disconnected. Then I connected the pwm in the same config and it could be controlled. So the digital out seems to be the issue, I tried to use 3 different pins 6, 7, and 8. All seem to produce the same issue.

@user1908460 it's also possible that the transistor is broken. The base resistor ist quite critical: if it is too low, you may exceed the base's or GPIO's current rating. If it is too high, the transistor is not operating in its saturation region, which leads to high power dissipation. Chances are that the transistor got destroyed during your previous attempts.

Good idea, I just tested two other ones with the lower resistance. Fan Also spins really slow. Connecting it to the 5V directly worked as well though.

@user1908460 set the GPIO high and measure a) voltage between GPIO and GND, b) voltage accross the base resistor, c) voltage between collector and emitter. A picture of your wiring might also help.

there is a) 0.8-0.9V over over GPIO-gnd, b) 0.24V over the resistor (120ohm), and c) 7.7V over collector-emitter.
I also tested GPIO-GND w/o any load and that was 5V.

I also did the same measurement when connecting the base resistor to 5V of the arduino instead of GPIO
a) 5V from 5V-GND
b) 4V over resistor
c) 0.1V from collector-emittor

@user1908460 the GPIO is dead. It may still work with a MOSFET but you better use a GPIO that isn't broken or replace the microcontroller. And -as I said- use a resistor between 500-1000Ohm. There's no need to load the GPIO with 36mA for your little load. That's very close to the maximum rating.

Thanks, I will order another arduino as well and test both, and find an 500-1000ohm resistor.

@user1908460 you can use 3 of the 2k2 in parallel. Btw if I would do it today, I'd also use a MOSFET like Majenko suggested.

OK, yeah since I already ordered the MOSFET, I will follow your advice. I used the transistor since I had it laying around, no need to wait for shipment....

@user1908460 you can use your 120Ohm as gate resistor for the MOSFET ;)

super thanks, yeah I would've just guessed something and probably broke something again :P


text:
Arduino controlled 25A 12V DC relay
I have an air compressor that I often give difficult tasks, where the compressor needs to run longer than it was designed for.  So it gets close to overheating, which requires periodically giving the compressor some "cool down" time, turned off.
Rather than walk into my garage every couple of minutes to turn the compressor on or off, I'd like to automate the process with a little arduino board.
The problem is the compressor is run by a 25A 12V DC line.  Most relays I can find that are Arduino compatible (3.3v DC control) max out at 10A.
I'm curious if there is a smart way to do this efficiently.  Two solutions that come to mind are:

Control 3 or 4 10A relays with the Arduino, and parallelize the current heading to the compressor across multiple relays.

Use one relay controlled by the Arduino, and use that relay to control a secondary big relay, that could control the 25A line.

Neither seems like a very efficient approach to the problem.  I don't know for certain but I worry that perhaps with (1), one relay might be a better conductor than the others, so perhaps one might eventually see a cascade of overheating relays.
Perhaps someone here that's more familiar with circuit design could suggest a better approach.
edit: After a little digging it looks like option (2) is the standard route most often traveled.

This is an OMRON relay that is powered by a 12VDC supply (0.167A), and can switch a 28VDC 30A line.   So I will double relay it, using an Adafruit featherwing to switch the 12VDC supply, which will then switch this big OMRON relay.   In my pile of old AC/DC converters I found a 1A 12V supply that's sufficient to run the OMRON relay.  Provided I haven't overlooked anything this is likely a decent solution.

(3) use some power mosfet + it's protection (but it might need some gate driver circut also)

The problem with (1) is actually that you will not be able to make all the relays close at the precise same moment, so one 10A relay will get the full 25A through it before the rest turn on. Baaaaaaaad! As KIIV says: use a MOSFET (or bank of MOSFETs).

Some folks sell a 30A logic level MOSFET RFP30N06LE or FQP30N06L for $0.95.

@DaveX: What is the role of the MOSFET?  I'm guessing you are suggesting that it would effectively replace the intermediate relay.  i.e. the arduino would trigger the MOSFET that would produce the 12V 0.167A signal to the big relay?   If so, I think maybe a different MOSFET is in order.

A MOSFET is an electronic switch that can replace a relay.  The  RFP30N06LE can replace a 30A 60V relay and be driven by the logic level produced by an arduino.  The 'logic level' feature is important, because normal MOSFETs might only be partially on with a 5V or 3.3V output, while logic-level MOSFETs are fully on.  Depending on the load, it might need a heatsink.  Better MOSFETs have lower Rd_on, wasting lower heat.

@DaveX: I can't find the RFP30N06LE, apparently it's discontinued.   The IRLB8721PBF seems similar.

Yes, the IRLB8721PBF is an good logic-level 30V 60A MOSFET, but it might struggle at 3.3v  Per the datasheet at https://www.infineon.com/dgdl/irlb8721pbf.pdf?fileId=5546d462533600a40153566056732591 Fig 1 & 2 it looks like a V_GS of 3V might not fully open for 25A 12V -- With it you might need a bit of driver like https://electronics.stackexchange.com/a/321880/30711 to get the gate voltage up to cover 20-30A.  Maybe the diode-resistor divider trick would be enough to push the 0-3.3V gate voltage to 0.7-4.0 and 40A?

Do not double relay it (at least not parallel aka Option 1).  Relays have a tendancy to bounce or take time.  This exposes you to a potential for only one relay to be connected for a time.  Worse, if someone decides to use the relays as high, low instead of closed, open it will short high to low for a time.
The series relay solution is sound but not efficient.  Relays are almost never the efficient approach (there are cases where infrequent switching occurs where a relay simply holding a position without power for long durations can be efficient).  A relay module is essentially a mosfet and a relay.  Mosfet controls the coil, and if you will have one of those, might as well go for a 12V mosfet of appropriate amperage.  I used to have some arduino compatible 3D printer heat bed mosfets that went up to 25A (on paper) so I can't imagine they're impossible to obtain.
You also mention digging power supplies for your relay.  If you are going so far as to need a 12V power supply, is there one providing for the compressor itself?  If so, could you just control the wall outlet AC that powers the supply?  Amperage would be a lot lower and AC can allow use of some rather nifty "Solid State Relay" devices (as well as relay modules, smart outlets, etc).

Thanks.  I'll have to learn how to use mosfets.  I think I knew more about circuits maybe 20-25 years ago.  Re-learning things in my 40's.   I find with little electronic devices like mosfets and transistors, it takes me a while to learn what the jargon means.  There is the "signal" current, and the other current, I'm not sure what it's name is.  But I'm slowly relearning the jargon.

Now searching on Digi-Key I'm confronted with yet more jargon. "Drain to source" voltage and "Drive voltage" ... and N-channel and P-channel.

Perhaps I could use a TIP120 to trip the 12V, 0.167A relay from my Arduino?

Regarding "do not double relay it", that's exactly what I've been doing.   As I mentioned, I'm using this to power an electric motor (4500 psi air pump).  It was working great until my air tank got to about the 4200 psi range. At this point the pictured OMRON relay started turning on and off rapidly.  Not certain what's going on there, but the current demand of the compressor was getting so high that I think there was some sort of feedback loop on the circuit, perhaps causing the smaller relay (connected to the arduino) to  cut out.

The rapid on-off cycles appear to be connected to the air compressor motor cycles.

keep it simple.  instead of buying the FET individually and having to size and mount a heat sink and cooling, just buy a module (search "arduino heat bed mosfet 12V 24V 30A" and look for one with a decent looking heat sink and naturally also the right specs).  cooling is often the limiting factor for current limits on these things.

I went with the solid state relay.  Seems to be working perfectly.


text:
Arduino fade in/out 5 leds circuit acting wierd
I have a simple arduino project with 5 leds, the project should start with led 1 fade through 50 millisec to reach full brightness, then led 2 and so on until led 5 then turn them all off and loop.
here is an image for the circuit (pardon the messy look my first time):

"all leds cathod are connected"
and here is the code :
 int led[5]={3,5,6,9,10};
// led pins array (pwm)
void setup() {
  // put your setup code here, to run once:
  for (int i = 0; i < 5; i++){
    pinMode(led[i], OUTPUT);
    }
    // set each pin as an output
}

void loop() {
  for (int i = 0; i < 5; i++){
    int pin = led[i];
    // storing the value of the current pin in a variable
    int j = 0;
    while(j <= 50){
      j++;
      delay(1);
      analogWrite(pin,j*2);
    }
    /* the while loop is used to make the fade effect
    by increasing the duty cycle by 2% each millisec
    over 50 millisec */
  }
  delay(200);

  for (int z = 5; z > -1; z--){
    int pin = led[z];
    analogWrite(pin,0);
    }
    // turning off all leds
    delay(50);
}

the problem is as follows :
the first round of the loop the circuit acts as expected led 1 on then 2 etc then they all turn off and loops again, on loop 16 led 1 turns off and the loop continues only with leds from 2-5 and on loop 31 led 4 and 5 turns off and only led 2 and 3 keep on going.
Edit 1 : i just found something interesting on arduino's official page
(pins supporting pwm 3, 5, 6, 9, 10, 11 )
pwm frequency 490 Hz (pins 5 and 6: 980 Hz)
so could the frequency result in this error?
Edit 2 : the issue was resolved with a really wierd change in the code
the very first line of code " int led[5]={3,5,6,9,10};" i changed the size of the array from 5 to 6 like this " int led[6]={3,5,6,9,10};" and the issue was resolved, I discovered this while i was trying to use 4 leds and i forgot to change the size, if anyone could explain how did this change helped solve the problem ?

Your second loop (for (int z = 5; ...) starts with z=5, which is an out-of-bound array index and might produce unpredictable behaviour. This also explains why your "fix" worked (you simple made the array larger). Make the loop start with z=4.

You need one resistor for each LED. Otherwise, the brightness of one LED affects the brightness of the others.

Your problem may be in your count down code. Specifically this loop:
for (int z = 5; z > -1; z--){

Z starts at 5, and you then try and access element 5 of a 5-element array. That sounds reasonable until you remember arrays are 0-based, so there is no element 5, only elements 0-4.
So you're reading data that you shouldn't be reading. Just reading shouldn't have any effect though, so :shrug:...
Anyway, there's some "best practice" things you should do to improve your code:

Use 8-bit values to store your pins (uint8_t)
Make your pins array const so it's never modifyable
Replace your while loop with a simpler to understand and follow for loop
Keep your loops as simple count-up and use math to work out which array entry you want.
Keep variables to the smallest storage size needed for the values you're working with.

For example (untested):
const uint8_t led[5] = { 3,5,6,9,10 };
// led pins array (pwm)

void setup() {
  for (uint8_t i = 0; i < 5; i++) {
    pinMode(led[i], OUTPUT);
  }
}

void loop() {
  for (uint8_t i = 0; i < 5; i++){
    int pin = led[i];
    for (uint8_t j = 0; j < 50; j++) {
      delay(1);
      analogWrite(pin, j * 2);
    }
  }

  delay(200);

  for (int z = 0; z < 5; z++) {
    int pin = led[4 - z];
    analogWrite(pin, 0);
  }

  delay(50);
}

Also as noted in the comments you must have one resistor per LED and never connect all the cathodes together like that. The brightness of each LED is determined by the current flowing through it. That current is the current through the resistor, which is determined by the forward volgage of the LEDs. The more LEDs you have on the more that current is split between the LEDs. And different LEDs will have different forward voltages, and the lowest one will "win" affecting the current that the resistor allows. It's all a horrible mess and must be avoided at all costs. The only times you can have just one resistor for multiple LEDs are a) if you have a series chain of LEDs making them in effect just one LED with a higher forward voltage, or b) can absolutely guarantee that one and only one LED will ever be turned on at a time.

it sounds like the most reasonable issue, i will try it and accept the answer if it solved the issue but why changing the array size solved the problem

@AhmedH2O By changing it to a 6 element array it's valid to access elements 0-5. It's not valid to access them with a 5 element array.

Here is the @Majenko code output

The code same as the one posted in the other answer. You can find the simulation link here --> https://wokwi.com/arduino/projects/318609194610590292
I also hooked up a logic analyser and here is how it looks :) You can look how the Duty cyle is becoming larger afer every cycle.


text:
How to make Arduino to read 1X4 keypad multiple times?
I want to use 1X4 membrane keypad to enter  3 working parameters for LED string controlled by  Arduino mini. Keypad is attached to D2-D5 pins and LED is attached to pin 12. My objective is to set the following parameters:
frequency (4 values),
duty cycle (4 values),
run time 4 (values).
I need  Arduino to read keypad 3 times so I can enter  3 parameters. "Run time" In the sketch below has not been set. I want to use “while” to force Arduino to read the keys but arduino reads it once.  Only first “while” is working in the code and I can set cycle period. Second “while” does not work because the key has been already pressed and Arduino does not read keypad second time. Are there any means to use more than 1 "while" in the code or to use one while to read keypad 3 times?
Thank you.
   #define Key1 3 // key 1 attached to pin 3
    #define Key2 2 // key 2 attached to pin 2
    #define Key3 5 // key 3 attached to pin 5
    #define Key4 4 // key 4 attached to pin 4
    float period; // cycle time
    float power; // duty cycle
    float ontime; // ontime  time LED is on
    float rest;  // rest time LED is off
    const int ledPin =  12;      // the number of the LED pin

    void setup()
    {
      pinMode(Key1, INPUT_PULLUP);
      pinMode(Key2, INPUT_PULLUP);
      pinMode(Key3, INPUT_PULLUP);
      pinMode(Key4, INPUT_PULLUP);
      pinMode(ledPin, OUTPUT);
    }
    void loop() {
      digitalWrite(ledPin, LOW);
      while (digitalRead(Key1) == HIGH && digitalRead(Key2) == HIGH && digitalRead(Key3) == HIGH && digitalRead(Key4) == HIGH) {};

      int key1a = digitalRead(Key1);
      int key2a = digitalRead(Key2);
      int key3a = digitalRead(Key3);
      int key4a = digitalRead(Key4);

      if (!key1a) {
        period = 1000;
      }
      if (!key2a) {
        period = 2000;
      }
      if (!key3a) {
        period = 3000;
      }
      if (!key4a) {
        period = 4000;
      }

      while (digitalRead(Key1) == HIGH && digitalRead(Key2) == HIGH && digitalRead(Key3) == HIGH && digitalRead(Key4) == HIGH) {};

      int key1b = digitalRead(Key1);
      int key2b = digitalRead(Key2);
      int key3b = digitalRead(Key3);
      int key4b = digitalRead(Key4  );

      if (!key1b) {
        power = 10;
      }
      if (!key2b) {
        power = 20;
      }
      if (!key3b) {
        power = 50;
      }
      if (!key4b) {
        power = 80;
      }

      ontime = period * power / 100;
      rest = period - ontime;

      digitalWrite(ledPin, HIGH);
      delay(ontime);
      digitalWrite(ledPin, LOW);
      delay(rest);
    }

I want to use “while” ... why? ... what if it makes no sense to use "while"?

What makes sense?

it would make more sense to detect a button press at begining of loop() and set a variable to 0, 1, 2, 3 or 4 ... 0 = no button ... use a state variable to keep track of which parameter you are changing


text:
Handling non-standard I2C read response lengths with Wire library
I'm trying to read from a Sam&Wing XW12A 12 channel touch sensor IC using I²C. The IC responds to an address read packet with 16 uninterrupted bits representing its state.

However, since I²C usually uses 8 bit bytes separated with an ACK signal, the 9th bit is lost when the controller sends an ACK bit for the first 8 bits.

My current code, using the Wire library, is below:
Wire.beginTransmission(devAddr);
Wire.requestFrom((uint8_t)devAddr, 2);
uint16_t buf;
Wire.readBytes((uint8_t *)&buf, 2);

This will return a 16 bit value, with bits 0-7 correct, then bits 9-15 shifted along with bit 8 missing.
Is there a way to prevent the controller from sending ACK bits and read the continuous 16 bits using the Wire library? And if not, is there any other better approach than just bitbanging the signal manually?

Edit: I've translated the I2C section of the datasheet below.

Edit 2: To prove that there's an issue, I've captured oscilloscope traces while bitbanging the address read header to the IC (but not sending ACKs). I've included a capture for each pad being pressed (and none pressed), you can see that pad 8 occurs on the first clock pulse after pad 7. If the IC was implementing I²C correctly, I would expect a gap of one clock pulse at this point while the IC waits for an ACK from the controller.

what are datasheet sections 4.6.3 and 4.6.4 about?

I've added a translation of the I2C section of the datasheet to the question.

I think the documentation is just somewhat bad in that it doesn't show the an ACK where they almost certainly are.  Not having one there would make this not I2C and not compatible with things that are I2C for no particularly good reason. Did you confirm that is this actually a problem? Or are you just noticing the lack of an ACK in the documentation?

This is definitely a problem - the capture shown in the question is from an actual device using this IC, I can see that the bit representing PAD8 is missing in the response data, and should appear at the same point that the controler sends the ACK. I haven't been able to confirm that the bit value is set correctly by the target when the controller does not send an ACK yet, but it seems more likely to me that the I2C protocol implementation is non-standard than the IC's read data just omitting this pin state altogether.

I've managed to bitbang the address read byte to the IC and I can confirm that it does behave as defined in the datasheet, i.e. sends the 9th bit on the same clock pulse that the controller sends an ACK.

Don't know what to tell you. Section 4.6.3, when machine translated to English, seems to describe standard I2C behaviour for ACK/NAK at each 9th bit. You even received the four padding '1' bits on the end that they described to make the actual data bits, to be padded to 16. Anyway, if you want to do something like I2C but not have the ACK/NAK where it is required by the I2C standard, then yes you'd need to bit-bang. But, I don't see putting that as answer because I don't think it has anything to do with the actual problem. So far as I can tell, your diagram is just a better diagram.

Your translation of the datasheet states "The information is transmitted in bytes (8 bits), and the receiver generates a response at the 9th bit." So that 9th bit IS just the Acknowlegment. So from our perspective this is just plain I2C. We also only can go with the datasheet. Are you really sure that the bit for pad8 the ack bit?

Can you please explain in more detail why you think that the bit for Pad8 is missing? In the question I don't see much supporting your theory that the ack should not be used (besides the last image in the datasheet snippet. And I don't really trust that image)

I've edited my question to add oscilloscope captures for each pad being pressed while bitbanging the header. If the IC was implementing I²C correctly, I'd expect to see a gap of one clock pulse between pad 7 and pad 8 as the IC waits for the ACK signal from the controller, but you can see that pulse for pad 8 follows directly on from pad 7.

Your translation of the datasheet states "The information is transmitted in bytes (8 bits), and the receiver generates a response at the 9th bit." So that 9th bit IS just the Acknowlegment.
I think that the datasheet is just referring to the header here, i.e. the controller sends the 8 bits representing the address and the R/W flag, and the target responds with an ACK at the 9th bit.

Interestingly, I've noticed that the ICman SC12A IC seems to describe the same behaviour in its datasheet. It's a similar IC, but has slightly different functionality and doesn't seem to be a clone. I was initially thinking that there might be a 16 bit variant of I²C that's more common in the Chinese market, but now I'm leaning towards it being a mistake in one implementation that's been copied from manufacturer to manufacturer.

The for(bitnum=0;bitnum<16;bitnum++) loop in your linked ICman SC12A datasheet supports your assertion also. They read 16bits of data without any handling for the ACK/NACK that standard I2C requires in the middle. This seems spectacularly stupid on the chip-makers part. I suppose if you wanted you could use the I2C peripheral to read other things on the bus and then disable the I2C peripheral and bitbang their wacky2C protocol on the same pins, allowing them to coexist on the same lines.  At least, I think that could work.

Ultimately, if this question is properly answerable by anyone, it's probably going to be by you. In which case, you could rewrite it as more of a "How do I use the Sam&Wing XW12A 12 channel touch sensor IC with Arduino", maybe make reference how a conventional I2C reading code fails, and then present what you've learned above cleaned up in an answer. Just so they're not reading the saga.  If you go that route it may make more sense to delete this question and present the your own Q&A in one go under a new question.

As you already have a code for bitbanging it partly I would suggest using this and extend it to read the data bits. That shouldn't be that difficult at this point. It might be possible to get this working with your own changes in the Wire or a Software I2C library (the former is less probable), but probably it is not really worth the hassle. Though you might wanna go the extra mile and make a library specific for reading that sensor, which you could then publish on github for others.

If you happen to be on an AVR with a USI peripheral, this may give some hardware assistance, since it doesn't do I2C outright, but has the building blocks for it and, I think, this non-standard protocol. But, most of the AVR used with Arduino don't and it may not be worth doing this either. However, it is the closest thing that comes to mind for supporting hardware.


text:
strcpy_P increases IROM usage by 400%
Using ESP8266 (NodeMcu 1) in Arduino IDE:
I can't upload my sketch because a single call to strcpy_P seems to increase the IROM usage by about 400%: 25% total usage without the call, 100+% with the call.
And even more strange, it depends on the second parameter of strcpy_P (the source):
If a pointer to a char array is provided, the usage increases dramatically
  char * ptr = (char *) pgm_read_word (&myArrays[index]);
  char buffer [1500];

  strcpy_P (buffer, ptr); // can't upload, uses 100+% of available IROM

Whereas with PSTR as parameter (just to test) total size of sketch is just 25% of IROM, leaving everything else unchanged:
  char * ptr = (char *) pgm_read_word (&myArrays[index]);
  char buffer [1500];

  strcpy_P(buffer, PSTR("Test")); // Ok, does not increase sketch size /IROM  usage

What's going on here ?

When its not used it willbe optimized out by the compiler.

what is char * ptr = (char *) pgm_read_word (&myArrays[index]);? you read address from flash?

I try to dynamically access  (by index) char arrays stored in PROGMEM. and these are referenced in  const char* const myArrays[] PROGMEM = { arr1, arr2, arr3}

@chrisl:  No, I commented out all referenecs to "buffer" after that call and still it uses 100% of IROM

That doesn't necessarily mean, that it would be optimized out completely. The effect just sound very like optimization. Though I'm not an expert for the optimization.

I guess the problem is not the strcpy_P function, but your array. Without that function call, the entire array can be removed by the compiler (I presume it's not used anywhere else). As soon as you add code that definitely accesses it, it is included in the code and therefore increases the size of the program so much.


text:
Weird assembly output
I was taking a look at the disassembly for a loop of mine that seemed to be taking too long and I found these assembly instructions that I don't understand. Why does it load 0 into r25 and then do two adc r25, 25 instructions (which wouldn't do anything since r25 is 0). This is for an ATTiny84 by the way.
EDIT: In general I'm confused about why there are so many instructions required to set DDRA, DDRB, PORTA, and PORTB in the last loop. I feel like an LD to read portOuts[j], OUT to output, and increment of j should be all that's required. I've tried to separate what I think is the relevant part in the disassembly.
void loop() {
  set_sleep_mode(SLEEP_MODE_IDLE);
  button = false;
  DDRA = 0;
  DDRB = 0;
  PORTA = 255;
  PORTB = 255;
  do {
    sleep_mode();
  } while (!button);

//  int digits[4];
//  getTime(digits);
//
//  long lights = calcDisp(digits);
  static const byte highLow[28][2] = {{2, 0}, {2, 1}, {0, 3}, {1, 3}, {1, 0}, {3, 1}, {0, 1},
                                     {0, 2}, {3, 0}, {2, 4}, {3, 4}, {4, 3}, {0, 4}, {4, 0},
                                     {4, 1}, {1, 4}, {1, 5}, {5, 1}, {1, 2}, {5, 3}, {2, 3},
                                     {2, 5}, {5, 2}, {5, 4}, {4, 5}, {3, 5}, {4, 2}, {3, 2}};
  byte portOuts[112];
  byte nLed = 0;
  long lights = 0b00000000000000001111111111111111; // just a constant, for now
  for (byte b = 0; b < 16; ++b) {
    if (bitRead(lights, b)) {
      byte high = highLow[b][0];
      byte low = highLow[b][1];
      byte highA = regs[high][0];
      byte highB = regs[high][1];
      byte lowA = regs[low][0];
      byte lowB = regs[low][1];
      portOuts[4 * nLed] = (highA)|(lowA);
      portOuts[4 * nLed + 1] = (highB)|(lowB);
      portOuts[4 * nLed + 2] = (highA)|(1<<PA6);
      portOuts[4 * nLed + 3] = (highB);
      ++nLed;
    }
  }
  for (byte i = 0; i < 200; ++i) {
    for (byte j = 0; j < nLed * 4;) {
      DDRA = portOuts[j++];
      DDRB = portOuts[j++];
      PORTA = portOuts[j++];
      PORTB = portOuts[j++];
    }
  }

DISASSEMBLY
void loop() {
  set_sleep_mode(SLEEP_MODE_IDLE);
  button = false;
  DDRA = 0;
  DDRB = 0;
  PORTA = 255;
 228:   bb 24           eor     r11, r11
 22a:   ba 94           dec     r11
                                     {2, 5}, {5, 2}, {5, 4}, {4, 5}, {3, 5}, {4, 2}, {3, 2}};
  byte portOuts[112];
  byte nLed = 0;
  long lights = 0b00000000000000001111111111111111; // just a constant, for now
  for (byte b = 0; b < 16; ++b) {
    if (bitRead(lights, b)) {
 22c:   cc 24           eor     r12, r12
 22e:   ca 94           dec     r12
 230:   dc 2c           mov     r13, r12
 232:   e1 2c           mov     r14, r1
 234:   f1 2c           mov     r15, r1
  }
  return lights;
}

void loop() {
  set_sleep_mode(SLEEP_MODE_IDLE);
 236:   85 b7           in      r24, 0x35       ; 53
 238:   87 7e           andi    r24, 0xE7       ; 231
 23a:   85 bf           out     0x35, r24       ; 53
  button = false;
 23c:   10 92 a6 00     sts     0x00A6, r1      ; 0x8000a6 <button>
  DDRA = 0;
 240:   1a ba           out     0x1a, r1        ; 26
  DDRB = 0;
 242:   17 ba           out     0x17, r1        ; 23
  PORTA = 255;
 244:   bb ba           out     0x1b, r11       ; 27
  PORTB = 255;
 246:   b8 ba           out     0x18, r11       ; 24
  do {
    sleep_mode();
 248:   85 b7           in      r24, 0x35       ; 53
 24a:   80 62           ori     r24, 0x20       ; 32
 24c:   85 bf           out     0x35, r24       ; 53
 24e:   88 95           sleep
 250:   85 b7           in      r24, 0x35       ; 53
 252:   8f 7d           andi    r24, 0xDF       ; 223
 254:   85 bf           out     0x35, r24       ; 53
  } while (!button);
 256:   80 91 a6 00     lds     r24, 0x00A6     ; 0x8000a6 <button>
 25a:   88 23           and     r24, r24
 25c:   a9 f3           breq    .-22            ; 0x248 <main+0xec>
 25e:   ac e6           ldi     r26, 0x6C       ; 108
 260:   b0 e0           ldi     r27, 0x00       ; 0
 262:   90 e0           ldi     r25, 0x00       ; 0
 264:   80 e0           ldi     r24, 0x00       ; 0
  static const byte highLow[28][2] = {{2, 0}, {2, 1}, {0, 3}, {1, 3}, {1, 0}, {3, 1}, {0, 1},
                                     {0, 2}, {3, 0}, {2, 4}, {3, 4}, {4, 3}, {0, 4}, {4, 0},
                                     {4, 1}, {1, 4}, {1, 5}, {5, 1}, {1, 2}, {5, 3}, {2, 3},
                                     {2, 5}, {5, 2}, {5, 4}, {4, 5}, {3, 5}, {4, 2}, {3, 2}};
  byte portOuts[112];
  byte nLed = 0;
 266:   60 e0           ldi     r22, 0x00       ; 0
 268:   30 e0           ldi     r19, 0x00       ; 0
 26a:   20 e0           ldi     r18, 0x00       ; 0
 26c:   a9 01           movw    r20, r18
 26e:   44 0f           add     r20, r20
 270:   55 1f           adc     r21, r21
 272:   44 0f           add     r20, r20
 274:   55 1f           adc     r21, r21
  long lights = 0b00000000000000001111111111111111; // just a constant, for now
  for (byte b = 0; b < 16; ++b) {
    if (bitRead(lights, b)) {
 276:   26 01           movw    r4, r12
 278:   37 01           movw    r6, r14
 27a:   08 2e           mov     r0, r24
 27c:   04 c0           rjmp    .+8             ; 0x286 <__stack+0x27>
 27e:   75 94           asr     r7
 280:   67 94           ror     r6
 282:   57 94           ror     r5
 284:   47 94           ror     r4
 286:   0a 94           dec     r0
 288:   d2 f7           brpl    .-12            ; 0x27e <__stack+0x1f>
 28a:   40 fe           sbrs    r4, 0
 28c:   3d c0           rjmp    .+122           ; 0x308 <__stack+0xa9>
      byte high = highLow[b][0];
      byte low = highLow[b][1];
      byte highA = regs[high][0];
 28e:   ec 91           ld      r30, X
 290:   f0 e0           ldi     r31, 0x00       ; 0
 292:   ee 0f           add     r30, r30
 294:   ff 1f           adc     r31, r31
 296:   e0 5a           subi    r30, 0xA0       ; 160
 298:   ff 4f           sbci    r31, 0xFF       ; 255
 29a:   70 81           ld      r23, Z
      byte highB = regs[high][1];
 29c:   a1 80           ldd     r10, Z+1        ; 0x01
      byte lowA = regs[low][0];
 29e:   11 96           adiw    r26, 0x01       ; 1
 2a0:   ec 91           ld      r30, X
 2a2:   11 97           sbiw    r26, 0x01       ; 1
 2a4:   f0 e0           ldi     r31, 0x00       ; 0
      byte lowB = regs[low][1];
 2a6:   ee 0f           add     r30, r30
 2a8:   ff 1f           adc     r31, r31
 2aa:   e0 5a           subi    r30, 0xA0       ; 160
 2ac:   ff 4f           sbci    r31, 0xFF       ; 255
 2ae:   91 80           ldd     r9, Z+1 ; 0x01
      portOuts[4 * nLed] = (highA)|(lowA);
 2b0:   21 e0           ldi     r18, 0x01       ; 1
 2b2:   30 e0           ldi     r19, 0x00       ; 0
 2b4:   2c 0f           add     r18, r28
 2b6:   3d 1f           adc     r19, r29
 2b8:   24 0f           add     r18, r20
 2ba:   35 1f           adc     r19, r21
 2bc:   e0 81           ld      r30, Z
 2be:   7e 2e           mov     r7, r30
 2c0:   77 2a           or      r7, r23
 2c2:   f9 01           movw    r30, r18
 2c4:   70 82           st      Z, r7
      portOuts[4 * nLed + 1] = (highB)|(lowB);
 2c6:   e2 e0           ldi     r30, 0x02       ; 2
 2c8:   f0 e0           ldi     r31, 0x00       ; 0
 2ca:   ec 0f           add     r30, r28
 2cc:   fd 1f           adc     r31, r29
 2ce:   e4 0f           add     r30, r20
 2d0:   f5 1f           adc     r31, r21
 2d2:   2a 2d           mov     r18, r10
 2d4:   29 29           or      r18, r9
 2d6:   20 83           st      Z, r18
      portOuts[4 * nLed + 2] = (highA)|(1<<PA6);
 2d8:   e3 e0           ldi     r30, 0x03       ; 3
 2da:   f0 e0           ldi     r31, 0x00       ; 0
 2dc:   ec 0f           add     r30, r28
 2de:   fd 1f           adc     r31, r29
 2e0:   e4 0f           add     r30, r20
 2e2:   f5 1f           adc     r31, r21
 2e4:   70 64           ori     r23, 0x40       ; 64
 2e6:   70 83           st      Z, r23
      portOuts[4 * nLed + 3] = (highB);
 2e8:   24 e0           ldi     r18, 0x04       ; 4
 2ea:   30 e0           ldi     r19, 0x00       ; 0
 2ec:   2c 0f           add     r18, r28
 2ee:   3d 1f           adc     r19, r29
 2f0:   42 0f           add     r20, r18
 2f2:   53 1f           adc     r21, r19
 2f4:   fa 01           movw    r30, r20
 2f6:   a0 82           st      Z, r10
      ++nLed;
 2f8:   6f 5f           subi    r22, 0xFF       ; 255
 2fa:   26 2f           mov     r18, r22
 2fc:   30 e0           ldi     r19, 0x00       ; 0
 2fe:   a9 01           movw    r20, r18
 300:   44 0f           add     r20, r20
 302:   55 1f           adc     r21, r21
 304:   44 0f           add     r20, r20
 306:   55 1f           adc     r21, r21
 308:   01 96           adiw    r24, 0x01       ; 1
 30a:   12 96           adiw    r26, 0x02       ; 2
                                     {4, 1}, {1, 4}, {1, 5}, {5, 1}, {1, 2}, {5, 3}, {2, 3},
                                     {2, 5}, {5, 2}, {5, 4}, {4, 5}, {3, 5}, {4, 2}, {3, 2}};
  byte portOuts[112];
  byte nLed = 0;
  long lights = 0b00000000000000001111111111111111; // just a constant, for now
  for (byte b = 0; b < 16; ++b) {
 30c:   80 31           cpi     r24, 0x10       ; 16
 30e:   91 05           cpc     r25, r1
 310:   09 f0           breq    .+2             ; 0x314 <__stack+0xb5>
 312:   ac cf           rjmp    .-168           ; 0x26c <__stack+0xd>
 314:   68 ec           ldi     r22, 0xC8       ; 200
      portOuts[4 * nLed + 3] = (highB);
      ++nLed;
    }
  }

####################### START OF RELEVANT SECTION #############################

  for (byte i = 0; i < 200; ++i) {
    for (byte j = 0; j < nLed * 4;) {
 316:   41 15           cp      r20, r1
 318:   51 05           cpc     r21, r1
 31a:   99 f1           breq    .+102           ; 0x382 <__stack+0x123>
 31c:   30 e0           ldi     r19, 0x00       ; 0
 31e:   20 e0           ldi     r18, 0x00       ; 0
 320:   80 e0           ldi     r24, 0x00       ; 0
      DDRA = portOuts[j++];
 322:   e1 e0           ldi     r30, 0x01       ; 1
 324:   f0 e0           ldi     r31, 0x00       ; 0
 326:   ec 0f           add     r30, r28
 328:   fd 1f           adc     r31, r29
 32a:   2e 0f           add     r18, r30
 32c:   3f 1f           adc     r19, r31
 32e:   f9 01           movw    r30, r18
 330:   90 81           ld      r25, Z
 332:   9a bb           out     0x1a, r25       ; 26      STORE IN DDRA
 334:   e1 e0           ldi     r30, 0x01       ; 1
 336:   e8 0f           add     r30, r24
      DDRB = portOuts[j++];
 338:   21 e0           ldi     r18, 0x01       ; 1
 33a:   30 e0           ldi     r19, 0x00       ; 0
 33c:   2c 0f           add     r18, r28
 33e:   3d 1f           adc     r19, r29
 340:   2e 0f           add     r18, r30
 342:   31 1d           adc     r19, r1
 344:   f9 01           movw    r30, r18
 346:   90 81           ld      r25, Z
 348:   97 bb           out     0x17, r25       ; 23      STORE IN DDRB
      PORTA = portOuts[j++];
 34a:   e3 e0           ldi     r30, 0x03       ; 3
 34c:   e8 0f           add     r30, r24
    }
  }
  for (byte i = 0; i < 200; ++i) {
    for (byte j = 0; j < nLed * 4;) {
      DDRA = portOuts[j++];
      DDRB = portOuts[j++];
 34e:   a2 e0           ldi     r26, 0x02       ; 2
 350:   a8 0f           add     r26, r24
      PORTA = portOuts[j++];
 352:   21 e0           ldi     r18, 0x01       ; 1
 354:   30 e0           ldi     r19, 0x00       ; 0
 356:   2c 0f           add     r18, r28
 358:   3d 1f           adc     r19, r29
 35a:   2a 0f           add     r18, r26
 35c:   31 1d           adc     r19, r1
 35e:   d9 01           movw    r26, r18
 360:   9c 91           ld      r25, X
 362:   9b bb           out     0x1b, r25       ; 27      STORE IN PORTA
      PORTB = portOuts[j++];
 364:   8c 5f           subi    r24, 0xFC       ; 252
 366:   21 e0           ldi     r18, 0x01       ; 1
 368:   30 e0           ldi     r19, 0x00       ; 0
 36a:   2c 0f           add     r18, r28
 36c:   3d 1f           adc     r19, r29
 36e:   2e 0f           add     r18, r30
 370:   31 1d           adc     r19, r1
 372:   f9 01           movw    r30, r18
 374:   90 81           ld      r25, Z
 376:   98 bb           out     0x18, r25       ; 24      STORE IN PORTB
      portOuts[4 * nLed + 3] = (highB);
      ++nLed;
    }
  }
  for (byte i = 0; i < 200; ++i) {
    for (byte j = 0; j < nLed * 4;) {
 378:   28 2f           mov     r18, r24
 37a:   30 e0           ldi     r19, 0x00       ; 0
 37c:   24 17           cp      r18, r20
 37e:   35 07           cpc     r19, r21
 380:   84 f2           brlt    .-96            ; 0x322 <__stack+0xc3>   JUMP BACK TO START OF LOOP
 382:   61 50           subi    r22, 0x01       ; 1
      portOuts[4 * nLed + 2] = (highA)|(1<<PA6);
      portOuts[4 * nLed + 3] = (highB);
      ++nLed;
    }
  }
  for (byte i = 0; i < 200; ++i) {
 384:   41 f6           brne    .-112           ; 0x316 <__stack+0xb7>

        setup();

        for (;;) {
                loop();
                if (serialEventRun) serialEventRun();
 386:   01 15           cp      r16, r1
 388:   11 05           cpc     r17, r1
 38a:   09 f4           brne    .+2             ; 0x38e <__stack+0x12f>
 38c:   54 cf           rjmp    .-344           ; 0x236 <main+0xda>
 38e:   38 de           rcall   .-912           ; 0x0 <__vectors>
 390:   52 cf           rjmp    .-348           ; 0x236 <main+0xda>```

Would have to see more code to see what is going on - the compiler can move stuff around so that asm code could be based on source code somewhere else.

which wouldn't do anything since r25 is 0 ... not quite true ... think about what adc does

For example, there could be a jump somewhere to 30e after r25 had been updated to a new value. In this case the ldi r25,0 is just initializing the first pass and it would not be worth it to jump over the initial adds even though they dont do anything on that first pass. .

Also seems like r24 is coming into this block with a useful value, but that code is not shown.

The compiler optimized the computation nLed * 4 into a bit shift, as
Led << 2. It seems nLed is a single byte quantity. However,
nLed * 4 may not fit in one byte, and the semantics of the language
demands that nLed is promoted to an int before the computation. This
is done by extending the variable by a byte of zeros:
    ldi r25, 0

Now the register pair r25:r24 contains nLed extended to 16 bits.
Next step is to shift the whole thing left by two positions. This is
done by repeating this sequence twice:
    lsl r24
    rol r25

The first instruction shifts r24 to the left. The most significant bit
is stored as the carry flag. The second instruction “rotate left through
carry”, is similar to a shift except that the rightmost bit position is
filled by the carry. This is the way to shift a 16-bit value without
loosing a bit.
The instruction lsl and rol are actually aliases of add and adc
respectively. The disassembler does not care about aliases, and
translates the machine code to the most “canonical” instructions, which
is what you see.

Hi Edgar, that's really interesting! I just edited my post to include some additional information. 2 questions is it possible to avoid the promotion and is that what's happening with my j++ lines as well?

@Anubhav: 1. The promotion is demanded by the language, but if you write (byte)(nLed * 4) the compiler may realize it can optimize it out. 2. The statements DDRA = portOuts[j++]; and following require some address calculations. You may get better results by declaring portOuts as static, which would make its address a compile-time constant.

Thanks, that seemed to make it better. What made it really good was doing byte* p = portOuts; outside of my inner loop and then just incrementing that pointer. Now the compiler just generates an LDD and an out as expected.

Simple: adc has three operands. You seem look at it as if it had two :)


text:
ATTiny84 fuses reading as 0
I was programming my ATTiny84 when it randomly stopped being able to be programmed.
I have an external 32768 Hz crystal connected to it, and I have been using my Arduino UNO with the ArduinoISP sketch to program it. The following command was working at least once before, but isn't anymore:
C:\Users\Anubhav\Documents\ArduinoData\packages\arduino\tools\avrdude\6.3.0-arduino17/bin/avrdude -CC:\Users\Anubhav\Documents\ArduinoData\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf -v -pattiny84 -cstk500v1 -PCOM3 -b19200 -Uflash:w:C:\Users\Anubhav\AppData\Local\Temp\arduino_build_256583/watch.ino.hex:i -U lfuse:w:0xe6:m -U hfuse:w:0xdf:m -U efuse:w:0xff:m

I tried with -B 5 as well but that didn't seem to help either. The problems seems to be that it's always reading the fuses as 0x000000. This is my output:
avrdude.exe: Version 6.3-20190619
             Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
             Copyright (c) 2007-2014 Joerg Wunsch

             System wide configuration file is "C:\Users\Anubhav\Documents\ArduinoData\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf"

             Using Port                    : COM3
             Using Programmer              : stk500v1
             Overriding Baud Rate          : 19200
             AVR Part                      : ATtiny84
             Chip Erase delay              : 4500 us
             PAGEL                         : P00
             BS2                           : P00
             RESET disposition             : possible i/o
             RETRY pulse                   : SCK
             serial program mode           : yes
             parallel program mode         : yes
             Timeout                       : 200
             StabDelay                     : 100
             CmdexeDelay                   : 25
             SyncLoops                     : 32
             ByteDelay                     : 0
             PollIndex                     : 3
             PollValue                     : 0x53
             Memory Detail                 :

                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               eeprom        65     6     4    0 no        512    4      0  4000  4500 0xff 0xff
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               flash         65     6    32    0 yes      8192   64    128  4500  4500 0xff 0xff
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               lock           0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               lfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               hfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               efuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00

             Programmer Type : STK500
             Description     : Atmel STK500 Version 1.x firmware
             Hardware Version: 2
             Firmware Version: 1.18
             Topcard         : Unknown
             Vtarget         : 0.0 V
             Varef           : 0.0 V
             Oscillator      : Off
             SCK period      : 0.1 us

avrdude.exe: PAGEL and BS2 signals not defined in the configuration file for part ATtiny84, using dummy values
avrdude.exe: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.05s

avrdude.exe: Device signature = 0x000000 (retrying)

Reading | ################################################## | 100% 0.04s

avrdude.exe: Device signature = 0x000000 (retrying)

Reading | ################################################## | 100% 0.04s

avrdude.exe: Device signature = 0x000000
avrdude.exe: Yikes!  Invalid device signature.
             Double check connections and try again, or use -F to override
             this check.

avrdude.exe done.  Thank you.

How do I fix the Yikes!  Invalid device signature. error and why is it occurring?

you did not ask a question

Is the MCU running at 32kHz clock? Then ISP clock should be less than 1/4 of MCU clock frequency. So you should try to change the default #define SPI_CLOCK  (1000000/6) to value like 5000 in the ArduinoISP sketch.

Isn't the baudrate of 19200 too fast for a 32768 system clock?

@thebusybee that's serial speed between Computer and ArduinoISP (UNO). The ISP clock speed is hardcoded inside of ArduinoISP sketch (as far as I know)

Ah, thanks for clarification!

@KIIV that fixed it, thanks! If you submit as an answer I can mark it as accepted.

As noted in question, the 32kHz crystal is used as a clock source and also at least the first programming was working.
The ArduinoISP sketch has hardcoded ISP clock speed and ISP clock has to be at most 1/4 of MCU speed. So the ArduinoISP sketch SPI_CLOCK has to be set to the much lower value than default 166kHz, which is way too fast for 32kHz MCU clock. The safe value is about 5000 (5kHz)
#define SPI_CLOCK 5000   // (1000000/6)

There is also baud_rate settings for the avrdude, but it's just communication speed between computer and ArduinoISP programmer and changing it won't change SPI_CLOCK (which is ISP clock).


text:
Serial.print() not fully printing
println() function is being used to send AT commands to GSM module.
sim800l.println("AT+CLTS=1");
  delay(3000);
  sim800l.println("AT+COPS=2");
  delay(3000);
  sim800l.println("AT+COPS=0,0");
  delay(3000);

But problem is the output -
AT+CLTS=1

OK
AT+COP

The command AT+COP did not print fully? Why?
Minimal Reproducable Example -
#include <SoftwareSerial.h>    //Library required for serial communication
char MYDATA[18];
SoftwareSerial sim800l(3, 2); // RX,TX for Arduino and for the module it's TXD RXD, they should be inverted
void setup() {
  Serial.begin(9600); //Start the serial interface on 9600
  sim800l.begin(9600);
  delay(100);
  // AT command to set sim800l to SMS mode
  sim800l.println("AT+CMGF=1");
  //Serialcom();
  delay(100);
  // Set module to send SMS data to serial out upon receipt
  sim800l.println("AT+CNMI=2,2,0,0,0");
  delay(100);
  sim800l.println("AT+CLTS=1");
  delay(3000);
  sim800l.println("AT+COPS=2");
  delay(3000);
  sim800l.println("AT+COPS=0,0");
  delay(3000);
   sim800l.println("AT+CCLK?");
  Serial.find("+CCLK: \"");
  Serial.readBytesUntil('\+', MYDATA, 17);

}

void loop() {
 Serial.print(MYDATA);
}

How / Where do you see the output and the response?

@DataFiddler Arduino Serial Monitor

Could you provide a minimal, complete, reproducible example?
https://stackoverflow.com/help/minimal-reproducible-example

... please expand your code snippet to show this Serial Monitor output, too (at least). A minimal but complete test sketch were even better, of course.

Nothing in that code should print to the serial monitor. Show all your code.

@Majenko Ok Ok please wait a minute. till then sim800l is Software Serial library.

@Majenko Please See.

@FilipFranik Please see.

@DataFiddler Please see.

Thanks for the changed code: You send some commands to your sim800l. Then you try to read from Serial. If there should arrive anything, you return a few of those characters repeatedly forever.Your Serial.find will probably time out. Your Serial.readBytesUntil will probably timeout too, and will get you at most 17 characters.

BTW: warning: unknown escape sequence: '\+' in your readBytesUntil

You're overflowing the serial receive buffer. There's only a limited amount of space (64 bytes normally, maybe less in SoftwareSerial) for receiving data before you must read it or lose data. Since you are just blindly throwing commands at the SIM800 and not doing anything with its responses until right at the end all that incoming data fills the receive buffer to overflowing.
Your methodology is flawed (not your fault, the examples on the internet are all rubbish and teach you the wrong way of doing things). What you should be doing is issuing a command then receiving the response back and parsing it to see if the command was successful or not, and retrieve any information that the response may include that you would want to know.

I do not want any  info from the commands. I just want to blindly issue the command. How can I empty the buffer?

Read it.  Or if you don't care what it returns why are you even bothering to display anything at all?

Because the last command, I want to read the AT+CCLK result. My module does not gets latest time. So the all commands are neccessary so that AT+CCLK returns correct date.

So you do want to read and interpret the responses then. At the very least you should be reading after every command and looking for either OK or ERR and discarding everything else.

I am very confused. If I open my own minimal reproducable example, there is no serial output. Then how come I was getting the output in my original code?

No idea. Write yourself a simple line-by-line reader / comparison routine that you can run after each command (except the one you're interested in) that returns a TRUE/FALSE result depending on if it finds OK or ERR. Do things properly from the start and things will be simpler later one.

Isn't there some command to empty Serial Buffer?

Yes. read. while (sim800l.available()) { sim800l.read(); }


text:
Splitting a string in arduino from computer
I am having an issue splitting an incoming string from a computer program to arduino.
The incoming format is as follows:
123.456,987.654 \r\n
The comma separates the two values.
code is this(edit to add code most likely too many variables):
char c;
String com;
String targetstr;
String actualstr;
bool newdata = true;
float target =1;
float actual = 5;
float diff;
int pwm = 0;
float firstup = 2.75;
float firstdown = 2.25;
float intensifier = 5;
unsigned long lasttime = 0;
unsigned long currenttime = 0;
int watchdog = 1000;

void setup() {
  // put your setup code here, to run once:
Serial.begin(19200);
dac.begin(0x60);
}

void loop() {
  // put your main code here, to run repeatedly:
currenttime = millis();

while(Serial.available()>0&&newdata == true){
  c = Serial.read();
// switched to '\r' from '\n' for testing.
  if(c == 0x0D){}

  if(c ==0x0A){
  targetstr = getValue(com,0x2C,0);
  //targetstr = com.substring(0,com.indexOf(0x2C));
  target = targetstr.toFloat();
  actualstr = getValue(com,0x2C,1);
  //actualstr = com.substring(com.indexOf(0x2C)+1);
  actual = actualstr.toFloat();
  com = "";//reset string
  diff = actual - target;
  newdata = false; //reset flag
  lasttime = currenttime;
  //Serial.print("Diff = ");
  //Serial.println(diff);
  Serial.print("Tgt ");
  Serial.print(targetstr);
  Serial.print(" Act ");
  Serial.println(actualstr);
  }
  else{
    com += c;
  }

The getValue is an example that I found on stack exchange
String getValue(String data, char separator, int index)
{
    int found = 0;
    int strIndex[] = { 0, -1 };
    int maxIndex = data.length() - 1;

    for (int i = 0; i <= maxIndex && found <= index; i++) {
        if (data.charAt(i) == separator || i == maxIndex) {
            found++;
            strIndex[0] = strIndex[1] + 1;
            strIndex[1] = (i == maxIndex) ? i+1 : i;
        }
    }
    return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}

So I have attempted two different ways to make this work. If I use the arduino serial monitor the code executes perfectly, but if I use the computer program it will not split the values.
In a serial monitor this is the sent code to the arduino via serial monitor(hex and ascii)
31 32 33 2E 34 35 36 2C 34 35 36 2E 31 32 33 0A   123.456,456.123.
and this is the arduino response
54 67 74 20 31 32 33 2E 34 35 36 20 41 63 74 20 34 35 36 2E 31 32 33 0D 0A                         Tgt 123.456 Act 456.123..
And this is code sent from the computer program to arduino:
31 36 31 2E 39 35 32 2C 31 35 30 2E 38 30 30 0D 0A    161.952,150.800..
arduino response:
54 67 74 20 2E 39 35 32 2C 31 35 30 2E 38 30 30 0D 20 41 63 74 20 0D 0A                   Tgt 161.952,150.800. Act ..
I am not sure of the reason of not splitting, I have tried ascii and hex in the code for the comma, as well as two methods of actually splitting.
What are some other things I can try?

Show the rest of the code.  Are you trying to do all of this with the String class?  This would be simpler with the data in a char array.  If c was a pointer to the char you're on then you could use atof on that and get a float, then find the comma and use atof again.  You're about to ask me for an example or something and that's not really possible without knowing what else you got going on here.

I was trying to minimize the code but keep it relevant. c is a char that gets wrapped into a string 'com'.. here is everything else in that part of the code.

Why would you "wrap" a char array into a String?  Just use the char array.

One problem that you have is that you start trying to extract the string while you are still reading it in.  I'm not sure how that works at all...  Is there an end marker to this packet?  Could you read to 7 char after the comma or something?  Either way, you need to read in the whole string before you start trying to convert it.  You can't convert what you haven't received yet.  If c==Ox0A where you start trying to convert that string, the actual first digit is still sitting in the buffer waiting to be read.

I tested your sketch with the data sent by your PC program, and it works as expected. Note, however, that since the string you send ends with \r\n, and you read up to the \n, the response of the Arduino ends in \r\r\n. You may want to replace if (c == 0x0A) by if (c == '\r' || c == '\n'). Note also that you can write ',', '\r' and '\n' instead of 0x2C, 0x0D and 0x0A respectively, and that would make the code easier to understand.

The reason I had them in hex was to test.. originally I had it as '\n' and ','  the \n at the end is the end marker

Do you have the code for the PC app? Did you write it? If so, what language was it written in?

I cannot comment on the pc app... I can sure ask though... im curious as to why it would matter


text:
how can i download a file with http from sd card using the SdFat.h
I use the Arduino IDE 1.8.10 and the esp8266 core 2.7.1 and the Wemos-D1 with SD Card Module
For the SD Card i use the SdFat.h library, because i need to set the timestamp for the uploaded file.
I am not a expert to arduino programming.
Currently my scetcch can this:
List Files from the SD Card on a webpage and show Filename and Filesize. Working.
Delete selected File. Working.
My Goal:
Download a File over http from the SD Card to my Windows PC.
Upload a File over http to SD Card with Timestamp from the original File.
With sd.h a simple Upload is working. But the Timestamp is every time 1.1.2020 01:00
My Includes:
#include "SdFat.h"
#include "sdios.h"
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266mDNS.h>

My Old code with sd.h for download:
void SD_file_download(String filename){
  if (SD_present) {
    File download = SD.open(filename);
    if (download) {
      filename.replace(" ","_");
      int last_slash = filename.lastIndexOf('/') + 1;
      filename = filename.substring(last_slash);
      server.sendHeader("Content-Type", "text/text");
      server.sendHeader("Content-Disposition", "attachment; filename="+filename);
      server.sendHeader("Connection", "close");
      server.streamFile(download, "application/octet-stream");
      download.close();
    } else del = "2";
  } else ReportSDNotPresent();
}

My new Code for Download with SdFat.h:
void SD_file_download(String filename){
SdFile dl_file;
  if (SD_present) {
    if (dl_file.open(filename.c_str())) {
      filename.replace(" ","_");
      int last_slash = filename.lastIndexOf('/') + 1;
      filename = filename.substring(last_slash);
      server.sendHeader("Content-Type", "text/text");
      server.sendHeader("Content-Disposition", "attachment; filename="+filename);
      server.sendHeader("Connection", "close");
        size_t sent = server.streamFile(dl_file, "application/octet-stream");
      dl_file.close();
    } else del = "2";
  } else ReportSDNotPresent();
}

If i compile i get many errors
In file included from F:\Eigene Dateien\Arduino\esp_fileserver05\esp_fileserver05.ino:14:0:

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WebServer\src/ESP8266WebServer.h: In instantiation of 'size_t esp8266webserver::ESP8266WebServerTemplate<ServerType>::streamFile(T&, const String&, HTTPMethod) [with T = sdfat::SdFile; ServerType = WiFiServer; size_t = unsigned int]':

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WebServer\src/ESP8266WebServer.h:177:50:   required from 'size_t esp8266webserver::ESP8266WebServerTemplate<ServerType>::streamFile(T&, const String&) [with T = sdfat::SdFile; ServerType = WiFiServer; size_t = unsigned int]'

F:\Eigene Dateien\Arduino\esp_fileserver05\esp_fileserver05.ino:211:60:   required from here

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WebServer\src/ESP8266WebServer.h:185:58: error: 'class sdfat::SdFile' has no member named 'size'

 _streamFileCore(file.size(), file.name(), contentType);

                                                      ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WebServer\src/ESP8266WebServer.h:185:58: error: 'class sdfat::SdFile' has no member named 'name'

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WebServer\src/ESP8266WebServer.h:187:21: error: no matching function for call to 'WiFiClient::write(sdfat::SdFile&)'

   contentLength = _currentClient.write(file);

                 ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WebServer\src/ESP8266WebServer.h:187:21: note: candidates are:

In file included from C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WiFi\src/ESP8266WiFi.h:39:0,

             from F:\Eigene Dateien\Arduino\esp_fileserver05\esp_fileserver05.ino:12:

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WiFi\src/WiFiClient.h:59:18: note: virtual size_t WiFiClient::write(uint8_t)

virtual size_t write(uint8_t) override;

              ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WiFi\src/WiFiClient.h:59:18: note:   no known conversion for argument 1 from 'sdfat::SdFile' to 'uint8_t {aka unsigned char}'

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WiFi\src/WiFiClient.h:60:18: note: virtual size_t WiFiClient::write(const uint8_t*, size_t)

virtual size_t write(const uint8_t *buf, size_t size) override;

              ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WiFi\src/WiFiClient.h:60:18: note:   candidate expects 2 arguments, 1 provided

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WiFi\src/WiFiClient.h:62:10: note: size_t WiFiClient::write(Stream&)

size_t write(Stream& stream);

      ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WiFi\src/WiFiClient.h:62:10: note:   no known conversion for argument 1 from 'sdfat::SdFile' to 'Stream&'

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WiFi\src/WiFiClient.h:65:10: note: size_t WiFiClient::write(Stream&, size_t)

size_t write(Stream& stream, size_t unitSize) __attribute__ ((deprecated));

      ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WiFi\src/WiFiClient.h:65:10: note:   candidate expects 2 arguments, 1 provided

In file included from C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Stream.h:26:0,

             from C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/HardwareSerial.h:32,

             from C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Arduino.h:245,

             from sketch\esp_fileserver05.ino.cpp:1:

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:76:23: note: size_t Print::write(int8_t)

     inline size_t write(int8_t c) { return write((uint8_t) c); }

                   ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:76:23: note:   no known conversion for argument 1 from 'sdfat::SdFile' to 'int8_t {aka signed char}'

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:75:23: note: size_t Print::write(char)

     inline size_t write(char c) { return write((uint8_t) c); }

                   ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:75:23: note:   no known conversion for argument 1 from 'sdfat::SdFile' to 'char'

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:73:23: note: size_t Print::write(long unsigned int)

     inline size_t write(unsigned long t) { return write((uint8_t)t); }

                   ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:73:23: note:   no known conversion for argument 1 from 'sdfat::SdFile' to 'long unsigned int'

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:72:23: note: size_t Print::write(long int)

     inline size_t write(long t) { return write((uint8_t)t); }

                   ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:72:23: note:   no known conversion for argument 1 from 'sdfat::SdFile' to 'long int'

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:71:23: note: size_t Print::write(unsigned int)

     inline size_t write(unsigned int t) { return write((uint8_t)t); }

                   ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:71:23: note:   no known conversion for argument 1 from 'sdfat::SdFile' to 'unsigned int'

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:70:23: note: size_t Print::write(int)

     inline size_t write(int t) { return write((uint8_t)t); }

                   ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:70:23: note:   no known conversion for argument 1 from 'sdfat::SdFile' to 'int'

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:69:23: note: size_t Print::write(short unsigned int)

     inline size_t write(unsigned short t) { return write((uint8_t)t); }

                   ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:69:23: note:   no known conversion for argument 1 from 'sdfat::SdFile' to 'short unsigned int'

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:68:23: note: size_t Print::write(short int)

     inline size_t write(short t) { return write((uint8_t)t); }

                   ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:68:23: note:   no known conversion for argument 1 from 'sdfat::SdFile' to 'short int'

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:64:16: note: size_t Print::write(const char*, size_t)

     size_t write(const char *buffer, size_t size) {

            ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:64:16: note:   candidate expects 2 arguments, 1 provided

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:58:16: note: size_t Print::write(const char*)

     size_t write(const char *str) {

            ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:58:16: note:   no known conversion for argument 1 from 'sdfat::SdFile' to 'const char*'

exit status 1
Fehler beim Kompilieren für das Board LOLIN(WEMOS) D1 R2 & mini.

i can't use te line:File download = SD.open(filename); with sdfat.h because i get a compiler error "reference to 'File' is ambiguous"
The problem is this line: size_t sent = server.streamFile(file, "application/octet-stream");
How can i solve this problem?
Thank you for Help...

You got your naming backwards: “download” means “transfer from some remote host to the local system”, whereas “upload” is from the local system to a remote host. From the point of view of your sketch, the board it runs on (the Wemos) is the local system. The Windows PC is the remote host.

No, this is not the problem. With another library sd.h the download and upload works fine. But sd.h can not write timestamps to uploaded files. Therefore i must use the sdfat.h library. Upload means from pc to Wemos SD Card. Download means from Wemos SD Card to PC

Re “Upload means from pc to Wemos SD Card”: no, it doesn't, unless you are talking from the perspective of the PC (you are writing software for the PC). “Upload” means “send to the network”; “download” means “receive from the network”. Whatever your PC is uploading is a download on the Wemos.

you are right... if i see it from another perspective. But it does not solve the coding problem.

The ESP8266WebServer library is written to use SD.h. If you want it to use a different SD library you will have to re-write that library to use it.