text:
HTTPClient works with localhost but not server
I started to work with HTTPClient and the WiFly library to connect to an SSID and then send POST data to a server. When I was sending the data to my localhost, it was working on localhost, but when changing the URL to a server I am getting this response:

<title>400 Bad Request</title>

400 Bad Request

openresty

My code is the following:
#define HTTP_POST_URL "http://URL/insert.php"
#define HTTP_POST_DATA "181"
SoftwareSerial uart(2, 3);
WiFly wifly(uart);
HTTPClient client;
char get;

while (client.post(HTTP_POST_URL, HTTP_POST_DATA, 10000) < 0) {}

Looking at the constructor of POST in the HTTPClient library it is possible to use POST without defining the header and it will automatically create a default header:
int HTTPClient::post(const char *url, const char *data, int timeout)
{
  return connect(url, "POST", NULL, data, timeout);
}

int HTTPClient::post(const char *url, const char *headers, const char *data, int timeout)
{
  return connect(url, "POST", headers, data, timeout);
}

int HTTPClient::connect(const char *url, const char *method, const char *data, int timeout)
{
  return connect(url, method, NULL, data, timeout);
}

int HTTPClient::connect(const char *url, const char *method, const char *headers, const char *data, int timeout)
{
  char host[HTTP_MAX_HOST_LEN];
  uint16_t port;
  char path[HTTP_MAX_PATH_LEN];

  if (parseURL(url, host, sizeof(host), &port, path, sizeof(path)) != 0) {
    DBG("Failed to parse URL.\r\n");
    return -1;
  }

  if (!wifly->connect(host, port, timeout)) {
    DBG("Failed to connect.\r\n");
    return -2;
  }

  // Send request
  char buf[HTTP_MAX_BUF_LEN];
  snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\n", method, path);
  wifly->send(buf);

  // Send all headers
  snprintf(buf, sizeof(buf), "Host: %s\r\nConnection: close\r\n", host);
  wifly->send(buf);

  if (data != NULL) {
    snprintf(buf, sizeof(buf), "Content-Length: %d\r\nContent-Type: text/plain\r\n", strlen(data));
    wifly->send(buf);
  }

  if (headers != NULL) {
    wifly->send(headers);
  }

  // Close headers
  wifly->send("\r\n");

  // Send body
  if (data != NULL) {
    wifly->send(data);
  }

  return 0;
}

So I am not sure why it worked on localhost but on the hosting.
EDIT:
after logging it to console, this is the request I am sending:
POST /insert_gsr.php HTTP/1.1

Host: www.mywebsite.com
Connection: close

Content-Length: 3
Content-Type: text/plain

EDIT 2:
The example code:
https://github.com/Seeed-Studio/WiFi_Shield/blob/master/Examples/wifly_http/wifly_http.ino
is also throwing the same error.

When you get a code 400 that means that you are reaching the server, but your request format is not correct. Without providing information about that endpoint we cannot say how the request has to look like. And what do you mean with sending to my localhost? Do you have code on that mimics the actual servers function? Or do you mean that you just get a code 200 with "it works"? Currently I don't see why localhost should be relevant here

first I tested out the PHP script where I want to send my POST data on localhost using XAMPP, then I uploaded the same script to my server where it no longer works after I change the URL I am connecting to that of the server. You can see the request I am sending at the bottom of my question. I also used an online API tester tool where I sent the same format of the request as from the Arduino, where it works.

Since the code you posted works in 2 out of 3 cases, I would ask about the server code which it doesn’t work with and not the code you posted. I would also perform a test using curl against the script which your code can’t talk to.

So with localhost you mean your PC? Have you tested the PHP script on your server (without the Arduino; connecting from your PC to your server)? Did that work?

Yes the localhost was an apache server running on my PC on the same WiFi the Arduino connected to. And yes, the script works when calling directly from the browser. My theory is that it worked local, because the request didn´t leave the gateway and the format request gets validated when talking to a remote server. Neverthless, the logged request looks valid to me.

The new link in your edit 2 doesn't work for me. Are you sure it is correct?

Can you show us how you tested the php script with the request from your PC to your server? The error is definitely that the request is not correct and that might show us, what the difference is.

I´ve have updated the link for the example. The example is also not working and getting the same errror, therefore it is not my PHP script that is not working.
I think the library: https://github.com/Seeed-Studio/WiFi_Shield/blob/master/Examples/wifly_http/HTTPClient.cpp is not setting the correct headers, I tried to send more header details, like accept or user-agent but still getting incorrect request

if we can make the example from github work from edit 2, it will also work for my code, the library is quite old and I think its not setting headers according to today's standards and in my opinion, needs modification

Do the headers really have blank lines in there, or is that just an artefact of logging?

its just the log. Each line ends with \r\n

Please show us how exactly you have done the successful test from your PC. You obviously don't build the correct request, but we cannot really help you unless we know how exactly the request has to look. If we got the request that works and the one that doesn't work side by side we would look for differences. And what headers are needed depends on your server setup (which you didn't show) and not on the Arduino code.

The request is built here: https://github.com/Seeed-Studio/WiFi_Shield/blob/master/Examples/wifly_http/HTTPClient.cpp and I believe if we can make the example code work in edit 2 (a request for HTTP bin site), it will also work for my server, as it seems to be the common problem. The entire project can be downloaded and tested from the linked GitHub repository.  So if you can make the code work from EDIT 2, it will also work for me as only the destination URL was changed in my code. I tried it with no luck.

@chrisfodor Did you get this to work? I had a similar problem with httpclient due to the target URL being out on the internet and I had not told httpclient the gateway IP, umask etc.

@kiwiron no, I did not get this to work, I turned my attention away from the problem and I will be using localhost, but communicating with a server would be better.


text:
Can I configure an Arduino via NFC using PN532 with an iPhone as the source?
It seems clear that Apple has intentionally limited the possibilities with NFC, so I understand that I'm going against the grain here. However, I need to support Android and Apple for my device setup, so I'm hoping to work around the Apple restrictions by making my Arduino receive data from an iPhone by posing as an RFID card and accepting a write from my Adafruit PN532 breakout board. I've got my Arduino Uno connected to the board and successfully reading from RFID cards. So the question is can I do a read from an iPhone? I've been experimenting with NFCTools on my iPhone to see if I can stimulate any behavior on my Arduino by running the Adafruit example programs and putting my phone near the reader while activating a write. I haven't had any success yet.
My idea is to avoid requiring Bluetooth for Arduino setup. My configuration is very simple so I don't need anything with high bandwidth. The configuration is done rarely and always by a person who is nearby. It seems like leaving out Bluetooth capability out of my device will save on cost and power consumption (though I don't know how much). It would be really slick too since my customer wouldn't need to go into settings to connect with Bluetooth. Instead they just put their phone near the device and it gets configured!

so, you are asking if your iPhone is able to pose as an RFID card ... wouldn't that be a question for the iPhone crowd?

I'm asking in two directions-- can the iPhone be a Card for read purposes, or can the PN532 be a card for Write purposes. Anyway, I did some more research and it looks like BLE is a better connectivity solution for my needs and still has the magic feel of appearing in an app without going into Settings and explicitly connecting.

can the iPhone be a Card for read purposes? is not about arduino, so it is off topic here ... can the PN532 be a card for Write purpose is also not about arduino ... you may have a better chance of a good answer at a Adafruit forum

My understanding is that the PN532 is a reader/writer and will only want to communicate with passive nfc devices (an RFID card). Therefore, with a phone you cannot really communicate between the two in the way you want. Basically both your phone and the PN532 are going to only look for a passive device.

source: Stack Exchange

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

sort: votes


text:
Matrix Keyboard
I'm trying to program a mechanical keyboard running on the Arduino Pro Micro (5V/16MHz). I'm using a matrix approach (4x12), and while I believe the code and the wiring (both of which I've checked multiple times) are correct, I can't get the first two rows to work no matter what. I've tried wiring it up to other pins, which works, but only for two rows at a time, when I hook up all the 4 rows, the two ones on top don't work. The code:
/*cols and rows*/
byte rows[] = {2,3,4,5};
const int row_Count = 4;
byte cols[] = {6,7,8,9,10,14,15,16,18,19,20,21};
const int col_Count = 12;

byte keyboard[col_Count][row_Count];

void read_layout() {
    /*do the columns*/
    for (int col_Index=0; col_Index < col_Count; col_Index++) {
        /*setup for registering the column state*/
        byte cur_Col = cols[col_Index];
        pinMode(cur_Col, OUTPUT);
        digitalWrite(cur_Col, LOW);

        /*do the rows*/
        for (int row_Index=0; row_Index < row_Count; row_Index++) {
            byte row_Col = rows[row_Index];
            pinMode(row_Col, INPUT_PULLUP);
            keyboard[col_Index][row_Index] = digitalRead(row_Col);
            pinMode(row_Col, INPUT);
        }
        /*disable the column*/
        pinMode(cur_Col, INPUT);
    }
}

void print_layout() {
    for (int row_Index=0; row_Index < row_Count; row_Index++) {
        Serial.print(row_Index);
        Serial.print(F(": "));

        for (int col_Index=0; col_Index < col_Count; col_Index++) {
            Serial.print(keyboard[col_Index][row_Index]);
            if (col_Index < col_Count) Serial.print(F(", "));
        }
        Serial.println("");
    }
    Serial.println("");
}

void setup() {
    Serial.begin(115200);
    delay(2000);
    /*init the rows*/
    for(int i=0; i<row_Count; i++) {
        pinMode(rows[i], INPUT);
    }
    /*init the cols*/
    for (int i=0; i<col_Count; i++) {
        pinMode(cols[i], INPUT_PULLUP);
    }
}

void loop() {
    read_layout();
    print_layout();

}

This is the schematic, a "dirty sketch":

two ones on top is meaningless ... how are they connected?

have you checked if a matrix keypad library is available?

Did you "rotate" the rows, to see whether the port pins or the matrix give the issue? Did you try with a smaller number of rows, and increase it one by one? Why do you change the pin modes of the rows, they can always be INPUT_PULLUP? -- Unrelated: the condition in print_layout() does not prevent the printing of the last comma. col_Index is always lower than col_Count there. -- Unrelated: You can automate the calculation of the sizes, for example const int col_Count = sizeof cols / sizeof cols[0];.

@jsotola I made a dirty sketch, "two ones on top" refers to R1 and R2, and I'm not using the keypad library because I think it is unnecessary and apparently multiple key presses at the same time don't register.

@thebusybee I've tried switching around the row pins, there wasn't an issue with the "first two rows" in particular, the problem only began when I hooked up more than 2 rows to it, then only the "last two" would work. The idea with INPUT_PULLUP was to only check periodically whenever I wanted to, then switch to INPUT, I'm not sure if this makes sense because this is the first time I'm using this pinmode. Thanks for the other tips I've already implemented them.

Please add the sketch in your question, so it wont get lost over time. -- Do you really have all these diodes in series, for example 4 for the topmost row in the schematic? Their forward voltages add up, and the input might not recognize the "LOW" then. Please make an experiment with a static level on one column and measure the voltage at the rows' pin.

@thebusybee Not sure what you mean by "add the sketch", It's already in the OP, should archive it and post the link here or what? Anyways, you're right. I tried shorting one of the columns and it worked! But I want to have the diodes to prevent ghosting, how would you go about that? Connect the diodes in series but on the rows instead of the columns?

Leaving a link to an external resource in a comment is quite not "in the OP". ;-) I used the provided procedure and added it to your question; well, first it needs approval due to my low reputation.

@thebusybee, Ah, I apologize, I thought you meant the Arduino (code) sketch.

Apology accepted. :-D Well, it was your wording on the link to the schematic. ;-)

You are using the diodes in series, which leads to accumulating forward voltages in the lower rows of your schematic. Because of this accumulation the threshold for "low" will not be crossed, and the input pin cannot recognize a pressed key.
Instead, you should adopt this circuit (copied from "Keyboard Matrix Help" by Dave Dribin). Of course, you will put the cathods on your columns pins, and the anodes on the keys.

So the right circuit uses each diode-and-key combination in parallel, not in series.

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


text:
Why is the value of this uint32_t always 0?
Setting up a method to calculate ID3 frame sizes, but the variable frsz always returns 0. I need to pass this variable back to another method so the program can loop through the ID3 frames.
void frameInfo(File track, char frame[4], uint32_t ltwo[4], int32_t frsz) {
 uint8_t buff[4];
 track.seek(10);
 track.read((uint8_t *)frame, 4);

 track.seek(14);
 track.read((uint8_t *)buff,4);
 ltwo[0] = buff[0];
 ltwo[1] = buff[1];
 ltwo[2] = buff[2];
 ltwo[3] = buff[3];

 ltwo[0] = ltwo[0] * 2097152;
 ltwo[1] = ltwo[1] * 16384;
 ltwo[2] = ltwo[2] * 128;

 frsz = ltwo[0] + ltwo[1] + ltwo[2] + ltwo[3];

 track.rewind();
}

Am I missing some sort of initialization for this uint32?

What do you mean by “I cannot assign a value to the variable”? Of course you can. Do you mean you would like a variable of the caller to be modified?

I think the question implies that, Edgar.

let the function return the value

void frameInfo(File track, char frame[4], uint32_t ltwo[4], int32_t frsz) {

The way you did it, frsz is passed by value (ie. a copy is made, and you have changed the copy, not the original). To make it change outside the function you need to pass it by reference:
void frameInfo(File track, char frame[4], uint32_t ltwo[4], int32_t &frsz) {

Note the ampersand.

normal would be to return the value as return of the function. but we don't know the context.

That was what I was missing. Thanks Nick!


text:
Can't get 433 RF to work
I am trying to have two Arduino's to communicate to each other via 433Mhz units. My project is a bit more complex, but I since it was notworking I reduced it to most basic form in order to exclude the possibility of other issues.
Right now I have to Arduino Mega, a received and a transmiter. I am using the RadioHead library examples, to make sure my code is not to blame.

I am using the example code:
Transmiter:
#include <RH_ASK.h>
#include <SPI.h>

RH_ASK rf_driver;

void setup()
{
    rf_driver.init();
}

void loop()
{
    const char *msg = "Hello World";
    rf_driver.send((uint8_t *)msg, strlen(msg));
    rf_driver.waitPacketSent();
    delay(1000);
}

Receiver:
#include <RH_ASK.h>
#include <SPI.h>

RH_ASK rf_driver;

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

void loop()
{
    uint8_t buf[11];
    uint8_t buflen = sizeof(buf);
    if (rf_driver.recv(buf, &buflen))
    {
      Serial.print("Message Received: ");
      Serial.println((char*)buf);
    }
}

Other notes:

It seems the receiver works. I am using RC Switch sniffer and I can sniff other 433 remotes. But nothing coming from the sender

I already tried:

Ordering new radio modules
Variety of libraries: RadioHead, VirtualWire and a bunch of other things found online
Uploading the code with Arduino Create and with Arduino IDE

Any suggestions on that else to try to figure out where I am failing would be greatly appreciated.
Thanks.

You don't need any library to transmit text. You can simply connect the transievers to the respective UART Tx and Rx pins and have the arduinos Serial.print() to each other (it's half duplex, though). Try this to see if the used library is to blame.

If you are using the WL102-341 transmitter, it's operating voltage spec is 2.0 - 3.6VDC.

@VE7JRO that was indeed the problem. On the seller website it specifies it works with anything from 3 to 12, but I moved it from 5 to 3.3 and now it works. Thank you!


text:
using RTC for storage
I keep seeing stuff about this: https://www.arduino.cc/reference/en/libraries/rtcvars/ when looking for storage for a few variables that survive turning off and on, but then it is only on ESP8266.
The thing I am trying to understand is what it has to do with the RTC..  Other RTCs don't seem to have this arbitrary storage ability. Is the RTC in an ESP8266 nothing like any other RTC? Or is this really just some other storage on the chip? And what is the storage technology itself? If I am using an arduino uno, or just at avr chip, is there any unit I can attach that is or isn't part of an RTC with the same storage properties? Or does every RTC have this ability, and just need somebody to write the library?
According to this https://forum.arduino.cc/t/save-data-in-nonvolatile-memory/140801/2, the RTC memory of the the ESP8266 can be written to an infinite number of times, whereas an SD card will wear out if you update a value on it every second (like for a counter).
What technology is this "RTC memory" using that I can attach to my avr project?

the RTC memory of esp8266 is cleared if the module is without power. its content is preserved on reset.

oh.  I misunderstood. I thought there was a clock battery in there that kept it going. but I guess a nodemcu doesn't have a built in clock battery.  thanks.

since SD cards wear-level, and a 4gb card is as cheap as any, it would take a really really long time to wear one out just by writing a number once a second.

>>> 4000000000 / 60 / 60 / 24 / 365 126.83916666666667 good point

and I guess it'll keep writing my byte 8 bit number to the same byte until it wears out and then move on to the next one.

I just triied it ouy with a nodemcu @Juraj - you are totally correct.

Some RTC chips contain a small amount of battery-backed SRAM ("NVRAM" - Non-Volatile RAM) which you can use for whatever you like. This is just ordinary RAM which is powered by the small battery that keeps the RTC running.
Not all do, though, so check the specs for your chosen RTC chip.
For example, the DS1302 has:

31 x 8 Battery-Backed General-Purpose RAM

That's 31 bytes of storage you can use for what you like.
Conversely the DS3231 doesn't have any spare RAM at all.

Thanks.  "battery backed ram" - Now it all makes sense.  I guess it's SetMemory in https://github.com/Makuna/Rtc/blob/master/src/RtcDS1302.h

@Alex028502 Yep, and the associated GetMemory.


text:
Arduino u8glib Problem
I am Trying to make tetris on a 128x64 oled 1.3", and I am using the u8glib library. Here Is My Code:
#include "U8glib.h"

U8GLIB_SH1106_128X64 u8g(13, 11, 10, 9);

int val = -53;
int val2 = -53;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
 // u8g.firstPage();
  //draw();
}

static const uint8_t PROGMEM tetris1 [] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

static const uint8_t PROGMEM tetris2 [] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

void draw() {
  u8g.drawBitmapP(val, 41, 16, 64, tetris1);
}

void d() {

}
void draw2() {
 u8g.firstPage();
 do {
  u8g.drawBitmapP(val2, 41, 16, 64, tetris2);
  val2 += 1;
  delay(250);
 }while(u8g.nextPage());
}

void loop() {
  // put your main code here, to run repeatedly:
  u8g.firstPage();
  do {
    draw();
  }while (u8g.nextPage());
  draw2();
}

The Problem is that when I call draw2() it creates a new page only displaying the shape from function draw2(), but what I want is for the shape from function draw() to stay there. Is there anyway I can do this??

u8g.firstPage() starts a new page. Anything you want to appear on that page has to be drawn on that page.

Most monochrome LCDs and operate on a principle of "pages". A page in this context is not a whole screen, but one strip of pixels, often 8 pixels high.
U8G draws the screen using these strips. It iterates over the whole screen on a page-by-page basis (a strip at a time, that is) and draws the content. Any drawing functions within that iterative loop (between u8g.firstPage() and the last u8g.nextPage()) get called for each strip and only the portion that is within the strip being drawn will be rendered.
This of course overwrites everything else on the screen. To display something it has to be within this loop of drawing each page. If you draw something in one loop then draw something else in another loop the second loop will overwrite what was there already.
This also means that you should not do anything other than drawing in a page loop. No delays, no complex calculations, etc. You want that loop to operate as fast as possible. Do any calculations outside the loop then run the loop. This is why the loop is often separated out into its own "draw" function, so you do all your work, then "draw" it to the screen.
So to draw two tetris pieces both those pieces have to be rendered within the same .firstPage() ... .nextPage() loop.

Since it is going to overwrite anything after nextPage(), how do I know where the first shape was originally so that I can put in the same spot again while the other shape gets drawn?? And also, how can I detect collision of the pieces in u8glib?

By writing the functionality in your program. You know where things are because you knew where they were when you put them there.

but when I make tetris the shapes will be falling down at different random locations and I wont know where they fell. So how do i keep track of that?

And how will yo make them "fall"...?

In the draw2() function, I add 1 to the x value every 250 milliseconds, which causes it to move down.

Then you know where it is as you have the X variable.

Here's a tip: Tetris doesn't remember where every piece is. Once it has landed it's just a collection of square blocks and ceases to be a shape any more.

Oh ok thank you. Also do you know how I can get collision detection in u8glib as I will need to know when it touches another piece so it can stop there

You're thinking about it all the wrong way. u8glib is just a way of drawing to the screen. It's up to you to know where things are and if they collide. u8g won't do that for you.

oh alright. thank you for the help

@hellopeople Personally if I were writing it I wouldn't be working with shapes. I'd be working with single blocks - shapes are just collections of those blocks in certain arrangements. Then the whole playfield is just a list of "There is a block here, but no block here" as a grid. Probably I'd just have a single binary value per row, and arrange them in an array to make a grid that can be tested for the presence of a block in any position rapidly. A full row is then just one where all the bits are set to 1, and moving rows down is as simple as copying values in the array.


text:
Arduino Array Scope with SPI
when I try the following code the SPI works correctly (see oscilloscope plot)
#include <SPI.h>

void setup() {
  SPI.begin();
}

void loop() {
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE3));
  byte a[] = {0xC,0xFF,0xFF,0xFF};
  SPI.transfer(a, 4);
  SPI.endTransaction();
  delay(10);
}

However when I move the array declaration to the a global it doesn't work any more. (see next oscilloscope plot) Why is this?
#include <SPI.h>

byte a[] = {0xC,0xFF,0xFF,0xFF};

void setup() {
  SPI.begin();
}

void loop() {
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE3));
  SPI.transfer(a, 4);
  SPI.endTransaction();
  delay(10);
}

it is not necessarily anything related to SPI ... use byte a[] = {'a', 'b', 'c', 'd'}; and do serial.write(a[0]) to print a value to serial monitor ... see if the result is the same

From the code you show I don't see any problem. It should work. Hm...

When you call SPI.transfer(a, 4);, any "received data" is stored in your byte array, a[]. The original data is overwritten.
If you print out the contents of the array before and after the function call to SPI.transfer(), you will see in the serial monitor what is happening to your array contents.
Here are 2 test sketches to illustrate the difference between the array with a global scope, VS the one with a static scope.
Global Scope
// Sketch uses 2344 bytes (7%) of program storage space.
// Global variables use 193 bytes (9%) of dynamic memory.
#include <SPI.h>

byte a[] = {0xC,0xFF,0xFF,0xFF};

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

void loop() {
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE3));
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println();
  SPI.transfer(a, 4);
  SPI.endTransaction();
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println('\n');
  delay(1000);
}

Static Scope
// Sketch uses 2410 bytes (7%) of program storage space.
// Global variables use 193 bytes (9%) of dynamic memory.
#include <SPI.h>

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

void loop() {
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE3));
  byte a[] = {0xC,0xFF,0xFF,0xFF};
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println();
  SPI.transfer(a, 4);
  SPI.endTransaction();
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println('\n');
  delay(1000);
}

The following sketch should solve the problem. Using the const keword before the declaration of the b[] array is optional.
// Sketch uses 2436 bytes (7%) of program storage space.
// Global variables use 197 bytes (9%) of dynamic memory.
#include <SPI.h>
const byte b[] = {0xC,0xFF,0xFF,0xFF};

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

void loop() {
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE3));
  byte a[] = {0xC,0xFF,0xFF,0xFF};
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println();
  SPI.transfer(a, 4);
  SPI.endTransaction();
  memcpy(a, b, sizeof(b));
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println('\n');
  delay(1000);
}

One last edit. The compile size can be reduced by 66 bytes thanks to the static keyword.
// Sketch uses 2370 bytes (7%) of program storage space.
// Global variables use 197 bytes (9%) of dynamic memory.
#include <SPI.h>
const byte b[] = {0xC,0xFF,0xFF,0xFF};

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

void loop() {
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE3));
  static byte a[] = {0xC,0xFF,0xFF,0xFF};
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println();
  SPI.transfer(a, 4);
  SPI.endTransaction();
  memcpy(a, b, sizeof(b));
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println('\n');
  delay(1000);
}

For more information, see: Arduino.cc


text:
Is there any way to secure Esp32 BLE server?
I've got a project in which currently I am using Bluetooth classic (with SSP - Simple secure pairing) to communicate to my esp32 board with my android app, but Bluetooth classic serial communication is not supported on ios devices therefore I want to switch to using BLE instead, but I can't find any way to secure the BLE that will ship with the product!
Any help would be appreciated,
Thanks :)

you could use higher level routines like digest, shared secret, public key, etc.

could you please elaborate a bit, I didn't understand. Thanks for helping :)


text:
Using CD74HC4067 16-Channel Analog Multiplexer Demultiplexer is not working as expected
I am working on a project that needs multiple digital signals and I am considering the CD74HC4067 (on a break-board) to work as a multiplexer. More specifically i am trying to build a keypad with multiple ttp123 break-boards. Each ttp123 signal is connected to one of the 0-15 pins of the CD74HC4067. The S0-S3 pins are connected to digital Pins D6 to D9 on a pro mini. Signal is on A0 and EN is on A1. A1 and EN have a 4K7 resistor to ground. I power the setup with a separate 5v and the arduino is connected on a pc usb port.
I expect when a ttp123 is pressed to trigger a HIGH and this event to be passed to SIG pin. Here is my code:
//Using CD74HC4067 16-Channel Analog Multiplexer
//Mux control pins

int s0 = 6;
int s1 = 7;
int s2 = 8;
int s3 = 9;

//Mux in "SIG" pin
int SIG_pin = A0;
int EN_pin  = A1;

void setup(){
  pinMode(s0, OUTPUT);
  pinMode(s1, OUTPUT);
  pinMode(s2, OUTPUT);
  pinMode(s3, OUTPUT);
  pinMode(EN_pin, OUTPUT);

  digitalWrite(s0, LOW);
  digitalWrite(s1, LOW);
  digitalWrite(s2, LOW);
  digitalWrite(s3, LOW);
  digitalWrite(EN_pin, LOW);

  Serial.begin(9600);
  Serial.println("keypad interfacing_CD74HC4067 starting...");
}

void loop(){
  String a;
  //digitalWrite(EN_pin, HIGH);
  Serial.println(" press any key to continue ...");
  //digitalWrite(EN_pin, LOW);
  while (!Serial.available());
  while(Serial.available()) {

  //Loop through and read all 16 values
  for(int i = 0; i < 16; i ++){
    //Serial.print("Value at channel ");
    //Serial.print(i);
    //Serial.print("is : ");
    //Serial.println(readMux(i));

      float volts = readMux(i);

      Serial.print("Value at channel ");
      Serial.print(i);
      Serial.print(" is : ");
      Serial.print(volts);
      Serial.println();

    //delay(1000);
  }
  a= Serial.readString();// read the incoming data as string
}
}
float readMux(int channel){
  int controlPin[] = {s0, s1, s2, s3};

  int muxChannel[16][4]={
    {0,0,0,0}, //channel 0
    {1,0,0,0}, //channel 1
    {0,1,0,0}, //channel 2
    {1,1,0,0}, //channel 3
    {0,0,1,0}, //channel 4
    {1,0,1,0}, //channel 5
    {0,1,1,0}, //channel 6
    {1,1,1,0}, //channel 7
    {0,0,0,1}, //channel 8
    {1,0,0,1}, //channel 9
    {0,1,0,1}, //channel 10
    {1,1,0,1}, //channel 11
    {0,0,1,1}, //channel 12
    {1,0,1,1}, //channel 13
    {0,1,1,1}, //channel 14
    {1,1,1,1}  //channel 15
  };

  //loop through the 4 sig

  for(int j = 0; j < 4; j ++){
    digitalWrite(controlPin[j], muxChannel[channel][j]);
  }
  //read the value at the SIG pin
  int val = analogRead(SIG_pin);

  //return the value
  float voltage = (val * 5) / 1024.0;
  return voltage;
}

Just for simplicity, I have connected only one ttp123 on the system, ttp123 signal to channel12 on 74HC4067. With ttp123 touched, I would expect to get a high on SIG when I write {0,0,1,1}, to S0-S3. All other channels should be LOW. However here is what I get:
On my first run after a boot:
press any key to continue ...
Value at channel 0 is : 2.53
Value at channel 1 is : 2.58
Value at channel 2 is : 2.53
Value at channel 3 is : 2.60
Value at channel 4 is : 2.51
Value at channel 5 is : 2.55
Value at channel 6 is : 2.50
Value at channel 7 is : 2.52
Value at channel 8 is : 2.42
Value at channel 9 is : 2.47
Value at channel 10 is : 2.43
Value at channel 11 is : 2.50
Value at channel 12 is : 2.40
Value at channel 13 is : 2.43
Value at channel 14 is : 2.38
Value at channel 15 is : 2.44

and then after each sample run all channels seem to get lower values...
press any key to continue ...
Value at channel 0 is : 1.70
Value at channel 1 is : 1.76
Value at channel 2 is : 1.71
Value at channel 3 is : 1.78
Value at channel 4 is : 1.70
Value at channel 5 is : 1.76
Value at channel 6 is : 1.72
Value at channel 7 is : 1.77
Value at channel 8 is : 1.67
Value at channel 9 is : 1.72
Value at channel 10 is : 1.69
Value at channel 11 is : 1.76
Value at channel 12 is : 1.69
Value at channel 13 is : 1.73
Value at channel 14 is : 1.67
Value at channel 15 is : 1.74

and I get no HIGH on channel 12 as I should.
Is there a need for a pullup or pulldown resistors in this setup? Should I connect a resistor to each S0-S3 with ground? Why is this not working?
Edit:
When the system is resting I measure 4.93V at the ttp's Vs to GND and 0V TTP_SIGNAL to GND. When ttp's are touched TTP_SIGNAL to GND i measure a 3.94-3.88v. But the strange thing is that when i touch the ttp's I measure 2.xx Volts at all the mux channels. I think that there must be some kind of short circuit somewhere but it is not visible. The problem is that I can't test another CD74HC4067 since i  have only one right now. Unless there is another suggestion I will look for a couple of these (CD74HC4067)  as soon as possible.
Edit2:
I got hold of a new CD74HC4067 and connected just one capacitive touch pad. When nothing is touched/pressed, i get the following:
press any key to continue ...
Value at channel 0 is : 1.01
Value at channel 1 is : 0.90
Value at channel 2 is : 0.81
Value at channel 3 is : 0.62
Value at channel 4 is : 0.44
Value at channel 5 is : 0.42
Value at channel 6 is : 0.43
Value at channel 7 is : 0.43
Value at channel 8 is : 0.31
Value at channel 9 is : 0.28
Value at channel 10 is : 0.24
Value at channel 11 is : 0.18
Value at channel 12 is : 0.15
Value at channel 13 is : 0.23
Value at channel 14 is : 0.22
Value at channel 15 is : 0.13

When i touch the pad (connected to c0) i get:
press any key to continue ...
Value at channel 0 is : 4.15
Value at channel 1 is : 3.74
Value at channel 2 is : 3.75
Value at channel 3 is : 3.54
Value at channel 4 is : 3.76
Value at channel 5 is : 3.33
Value at channel 6 is : 2.88
Value at channel 7 is : 2.64
Value at channel 8 is : 3.77
Value at channel 9 is : 3.52
Value at channel 10 is : 3.07
Value at channel 11 is : 2.76
Value at channel 12 is : 2.04
Value at channel 13 is : 1.83
Value at channel 14 is : 1.67
Value at channel 15 is : 1.51

I measure volts between signal and ground at the capacitive touch pad, when touched i get 3.9v

You've mentioned separate supply, begginers loves to forgot ground connections. Anyway slowly changing adc readings somewhere far from 0 or 5 usually indicates floating input. You have to measure everything, test that mux separately...

@KIV thank you for your comment. The grounds of the two separate sources are connected. I will measure everything again and will come back.

Posting a schematic of how you have it wired will help a lot. Even a hand drawn schematic is better than a frizzy picture.

@Gil i edited the question as you suggested.

I got a new CD74HC4067 and tested it. I edited the post above. Any suggestions?

I finally managed to get a solution to my problem. There was a cabling and a software issue as well. Firstly, I pulled down the Signal with a 10K resistor. In this way I stopped having those random volt measurements.

Secondly, in the code, I had an elementary failure to initialize the A0 analog pin as:
pinMode(SIG_pin, INPUT);
Here is the final code:
// interfacing mux with tp223

//Mux control pins

const int s0 = 6;
const int s1 = 7;
const int s2 = 8;
const int s3 = 9;

//Mux in "SIG" pin
int SIG_pin = A0;
int EN_pin  = 10;

void setup(){
  pinMode(s0, OUTPUT);
  pinMode(s1, OUTPUT);
  pinMode(s2, OUTPUT);
  pinMode(s3, OUTPUT);
  pinMode(SIG_pin, INPUT);
  pinMode(EN_pin, OUTPUT);

  digitalWrite(s0, LOW);
  digitalWrite(s1, LOW);
  digitalWrite(s2, LOW);
  digitalWrite(s3, LOW);
  digitalWrite(EN_pin, LOW);

  Serial.begin(115200);
  Serial.println("keypad interfacing_CD74HC4067 starting...");
}

void loop(){

  //Loop through and read all 16 values
  for(int i = 0; i < 16; i ++){
      int val = readMux(i);

      if (val > 0) {
        Serial.print(i);
        Serial.print(" pressed ");
        Serial.print(val);
        Serial.println();
      }
  }

}
float readMux(int channel){
  int controlPin[] = {s0, s1, s2, s3};

  int muxChannel[16][4]={
    {0,0,0,0}, //channel 0
    {1,0,0,0}, //channel 1
    {0,1,0,0}, //channel 2
    {1,1,0,0}, //channel 3
    {0,0,1,0}, //channel 4
    {1,0,1,0}, //channel 5
    {0,1,1,0}, //channel 6
    {1,1,1,0}, //channel 7
    {0,0,0,1}, //channel 8
    {1,0,0,1}, //channel 9
    {0,1,0,1}, //channel 10
    {1,1,0,1}, //channel 11
    {0,0,1,1}, //channel 12
    {1,0,1,1}, //channel 13
    {0,1,1,1}, //channel 14
    {1,1,1,1}  //channel 15
  };

  //loop through the 4 sig
  for(int j = 0; j < 4; j ++){
    digitalWrite(controlPin[j], muxChannel[channel][j]);
  }
  //read the value at the SIG pin
  int val = digitalRead(SIG_pin);
  //return the value
  return val;
}


text:
Trouble understanding min and max parameters for the Servo motor

This picture is from arduino.cc .  Could someone please help me understand these parameters min and max? I was using TinkerCad taking input for the angle using a potentiometer (having mapped correctly the input from (0 to 1023) to (0 to 180) ) but i don't see any change when i vary either min or max in my code. The servo still goes to 180-deg position when input is 1023.

it is the pulse width of the control signal that has to be sent to the servo when commanded to move to its minimum and maximum positions

In your question you're referencing the servo library. You mention mapping ranges of 0-1023 (the sampling range of your potentiometer) and 0-180 (the degrees of rotary travel of the average hobby servo).
There is an additional important concept to get familiar with as you learn about servos. That is the Pulse Width Modulated (PWM) signal that the Arduino (or any other controller) uses to communicate with the servo to set what angle of rotation it should assume. PWM is used a few different ways in electronics, but in this scenario it is being used as a servo control signal, and the pulse width (measured as a time duration) communicates the required angle to the servo. The library you're referencing helps users by translating between angles and PWM pulse lengths. But under the covers servos always (close enough for our conversation anyway) receive a signal based on PWM.
Another complicating factor is that servos vary greatly. There is a loose convention that says that a pulse width of 1500 micro-seconds is centre position, 1000 micro-seconds is the minimum -90 degress (or 0 degrees depending on how you look at it), and 2000 micro-seconds is the maximum +90 (or 180) degrees. These match the defaults that @Bra1n notes in their answer.

(Diagram by Wikimedia user Hforesti - https://commons.wikimedia.org/wiki/File:Sinais_controle_servomotor.JPG, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=101951622)
But that convention is broken all the time. Some servos are capable of less than or greater than 180 degrees. Others use different pulsewidths to specify the maximum and minimum rotations. It's for this reason that the library allows the minimum and maximum pulsewidth (expressed in micro-seconds) to be specified for the particular physical servo being attached. This allows the library to correctly map to its range of travel.
Everytime you use a new type of servo (or consider buying one for a new project) you'll need to look at its datasheet to get the important information about how that servo works.
One last thought about traps for new players, I've also seen servo libraries which express the maximum and minimum servo PWM values in the range of 0-4096. Some people also express this as a % duty cycle (mixing the language of those other purposes I mentioned PWM is also used for). Knowing that these all map back to a PWM pulse width is useful for making sense as you learn more about servos. Good luck!

It's hard coded in the servo library (well it is on the ESp8266 version I used).
// The following values are in us (microseconds).
// Since the defaults can be overwritten in the new attach() member function,
// they were modified from the Arduino AVR defaults to be in the safe range
// of publicly available specifications. While this implies that many 180°
// servos do not operate the full 0° to 180° sweep using these, it also prevents
// unsuspecting damage. For Arduino AVR, the same change is being discussed.
 #define DEFAULT_MIN_PULSE_WIDTH      1000 // uncalibrated default, the shortest duty cycle sent to a servo
 #define DEFAULT_MAX_PULSE_WIDTH      2000 // uncalibrated default, the longest duty cycle sent to a servo
 #define DEFAULT_NEUTRAL_PULSE_WIDTH  1500 // default duty cycle when servo is attached

I discovered this when a servo attached to an ESP8266 was only moving half the expected angle so I modified the library (saving it as MyServo) and used that instead. You need to be careful when doing this as you can strip the servo gears if you try to move the servo outside its capable range.

Well I am a very beginner! Could you please guide me how I can learn this? What you said is a bit too advanced for me to understand. ( please bear with me). But I want to surely know what I should do to not strip my servo gears ( so what should min and max ) be set to? Maybe you could give some  detailed references.


text:
LILYGO TTGO T-Display cannot detect MPU 6050 Accelerometer, Gyroscope and Temperature Sensor
I've been trying to connect a MPU 6050 Accelerometer, Gyroscope and Temperature Sensor to a LILYGO TTGO T-Display to get readings displayed on the serial monitor (for starters). The wiring is pretty straightforward. I need to power up the MPU6050 with 3V, and connect the SDA and SCL. I followed this tutorial (https://randomnerdtutorials.com/esp32-mpu-6050-accelerometer-gyroscope-arduino/).
This is the code used:
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>

Adafruit_MPU6050 mpu;

void setup(void) {
  Serial.begin(115200);
  while (!Serial)
    delay(10); // will pause Zero, Leonardo, etc until serial console opens

  Serial.println("Adafruit MPU6050 test!");

  // Try to initialize!
  if (!mpu.begin()) {
    Serial.println("Failed to find MPU6050 chip");
    while (1) {
      delay(10);
    }
  }
  Serial.println("MPU6050 Found!");

  mpu.setAccelerometerRange(MPU6050_RANGE_8_G);
  Serial.print("Accelerometer range set to: ");
  switch (mpu.getAccelerometerRange()) {
  case MPU6050_RANGE_2_G:
    Serial.println("+-2G");
    break;
  case MPU6050_RANGE_4_G:
    Serial.println("+-4G");
    break;
  case MPU6050_RANGE_8_G:
    Serial.println("+-8G");
    break;
  case MPU6050_RANGE_16_G:
    Serial.println("+-16G");
    break;
  }
  mpu.setGyroRange(MPU6050_RANGE_500_DEG);
  Serial.print("Gyro range set to: ");
  switch (mpu.getGyroRange()) {
  case MPU6050_RANGE_250_DEG:
    Serial.println("+- 250 deg/s");
    break;
  case MPU6050_RANGE_500_DEG:
    Serial.println("+- 500 deg/s");
    break;
  case MPU6050_RANGE_1000_DEG:
    Serial.println("+- 1000 deg/s");
    break;
  case MPU6050_RANGE_2000_DEG:
    Serial.println("+- 2000 deg/s");
    break;
  }

  mpu.setFilterBandwidth(MPU6050_BAND_5_HZ);
  Serial.print("Filter bandwidth set to: ");
  switch (mpu.getFilterBandwidth()) {
  case MPU6050_BAND_260_HZ:
    Serial.println("260 Hz");
    break;
  case MPU6050_BAND_184_HZ:
    Serial.println("184 Hz");
    break;
  case MPU6050_BAND_94_HZ:
    Serial.println("94 Hz");
    break;
  case MPU6050_BAND_44_HZ:
    Serial.println("44 Hz");
    break;
  case MPU6050_BAND_21_HZ:
    Serial.println("21 Hz");
    break;
  case MPU6050_BAND_10_HZ:
    Serial.println("10 Hz");
    break;
  case MPU6050_BAND_5_HZ:
    Serial.println("5 Hz");
    break;
  }

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

void loop() {
  /* Get new sensor events with the readings */
  sensors_event_t a, g, temp;
  mpu.getEvent(&a, &g, &temp);

  /* Print out the values */
  Serial.print("Acceleration X: ");
  Serial.print(a.acceleration.x);
  Serial.print(", Y: ");
  Serial.print(a.acceleration.y);
  Serial.print(", Z: ");
  Serial.print(a.acceleration.z);
  Serial.println(" m/s^2");

  Serial.print("Rotation X: ");
  Serial.print(g.gyro.x);
  Serial.print(", Y: ");
  Serial.print(g.gyro.y);
  Serial.print(", Z: ");
  Serial.print(g.gyro.z);
  Serial.println(" rad/s");

  Serial.print("Temperature: ");
  Serial.print(temp.temperature);
  Serial.println(" degC");

  Serial.println("");
  delay(500);
}

The pinout config for the TTGO T Display is shown below:

I connected the pins based on this as follows:
TTGO        MPU6050
3V  ---->  Vcc
G   ---->  Gnd
22  ---->  SCL
21  ---->  SDA
But I keep getting the following error on the serial monitor.
ets Jul 29 2019 12:21:46

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1324
ho 0 tail 12 room 4
load:0x40078000,len:13508
load:0x40080400,len:3604
entry 0x400805f0
Adafruit MPU6050 test!
Failed to find MPU6050 chip

What is strange is that the MPU 6050 works perfectly fine with the same pin connection on the normal Node MCU ESP 32 system. Any idea why it won't work on the TTGO?

I had exactly the same error (Failed to find MPU6050 chip)on the same program with the same tutorial. I thought it was this, that, and an act of nature. I hade proven the MPU6050 worked fine and the ESP32 worked fine. EVENTUALLY I realised it was dead simple, the ESP32 ( a cheapo one) had different pinout to the one in the tutorial, SCL,SDA and 3.3v were in the wrong place even though the red LED illuminated on my MPU6050 board. Anyway I wired it correctly and it works just fine and the Webserver one too. I did not do the display one! ( Don't take anything for granted). I do not know which incarnation of the MPU6050 you are using but when using mine (looked identical as the one in the tutorial) on an ESP8266 the I2C addressing was a bit finicky and I had to take the address connection hard to GND  with a wire to get it to run consistently, that too caused the same error (Failed to find MPU6050 chip).


text:
Can this display's address be changed?
I need two displays hooked up to an Arduino MKR Wifi 1010, and I saw this video which shows how to do it: this video. I also would like to have a full color oled display about 1 inch big so I would like to use this display. But I don't believe that you can change the address and would not like to buy it until I find out if you can.
Thanks in advance.

The Adafruit display uses SPI. Different SPI devices can be selected via their respective CS (Chip Select) pins. You can connect the SPI bus (MOSI, MISO ans SCK) to multiple displays in parallel and choose which one to control by enabling their CS pin (although the display library will usually do this for you).

There are two different OLED screens in the links you shared.
1. OLED Display on Adafruit Link
The OLED display on the Adafruit link does not have an address as it communicates via the SPI interface.
2. OLED Display on YouTube Link
This OLED display communicates via I2C interface. OLED displays that communicate over the I2C interface have a slave address. This provides the possibility to connect devices with different slave addresses on the same I2C line. The address of this screen can only take two different values. If you solder the 0 Ω resistor to the left field, its address will be 0x7A; if you solder the 0 Ω resistor to the right field, its address will be 0x78.

Suggestions
This OLED display with 0.96" screen size communicates via I2C interface and its address can be changed. If a 0 Ω resistor is connected to the A0 pad, the I2C slave address of the OLED display will be 0x3D; otherwise the I2C slave address of the OLED display will be 0x3C.

If you have a address conflict the generic solution would be to use I2C mux that will switch between the circuits or use different hardware I2C or bitbang a software I2C.


text:
Servo keeps rotating
I use a 360° servo with a program I made on an Arduino Uno.
The program was meant to control two separate servos with two potentiometers on a breadboard.
When I used 180° and 90° servos, it worked fine, but when the 180° servo was swapped with a 360° servo, it kept spinning and spinning non-stop.
Could it be the knock-off board (not Arduino brand) I'm using?
Servo serX;    // create servo object to control a servo for x axis
Servo serY;    // create servo y axis

int pot1 = 0;  // potentiometer pin number on board
int pot2 = 1;  // potentiometer number 2
int val;       // variable to read the value from the analog pin
int val2;      // read value from other analog pin

void setup() {
  serX.attach(9);  // attaches the servo on pin 9 to the servo object
  serY.attach(10); // attach servo to number 10 pin
}

void loop() {
  val = analogRead(pot1);           // reads the value of the potentiometer
  val = map(val, 0, 1023, 0, 180);  // scale it to use it with the servo
  serX.write(val);                  // sets the servo position

  val2 = analogRead(pot2);          // reads the value of the potentiometer
  val2 = map(val2, 0, 1023, 0, 90); // scale it to use it with the servo
  serY.write(val2);                 // sets the servo position

  delay(15);                        // waits for the servo to get there
}

Is this a "continuous rotation" servo? If so then the "angle" defines the speed and direction of rotation, with 90° normally being "stop".

The "360°" you refer to is probably a continuous-rotation servo.
These servos behave more like motors than like the normal RC servos; the signal you send such a servo will determine its speed and direction, not its position, and a pulse width of 1.5 ms (the "90° setting") will make it stop.
There's an article on the Adafruit site where you can read more about this.


text:
I2C communication in Arduino
In Arduino I2C we have the following lines of code:
wire. beginTransmission(slave addrress)
wire.write(the byte want to send)
wire. endTransmission()

As we know in I2C the master must verifies the presence of the slave address and making it sure by getting an ack by the slave. Among the three function listed, who does this job? Is it wire. beginTransmission? in their website it's just mentioned it initializes communication with the slave. I want to know what happens during the execution of wire. beginTransmission from I2C perspective.
Also wire.endTransmission() releases the buffer data which was created by wire. write. So who examines the presence of the slave? The first function or the 3rd?

All the actual I2C communication is done in Wire.endTransmission(). Before that nothing is done on the I2C lines.
Wire.beginTransaction() only initializes the libraries buffer and saves the slave address in an internal variable. Wire.write() puts data into the internal buffer.
Wire.endTransmission() can then follow the I2C protocol. It generates a start condition on the bus, sends the address byte, checks for the slaves acknowledgement on the address byte, then sends the data bytes, each followed by the slaves acknowledgement. Finally it generates a stop condition.

it means suppose i forgot to write wire. beginTransmission, does that mean I can't execute wire.endTransmission? Because it looks like the latter is depended on the first? That is, wire. endTransmission isn't an independent function.

Wire.beginTransmission() primes the library for a master write transaction. So you need it before calling Wire.endTransmission(). What makes you think that any of these functions are independent? They are working for the same hardware interface. You need to call them just as the library supposes you to.


text:
uint8_t issues when linking libraries outside of INO file
I've been trying to start my project out split into multiple files, knowing it will grow. I was templating it off of how I've done C++ files in the past: classes in an individual .h/.cpp pair and linked into the main file. I'm using the OneBitDisplay library for my OLEDs. When I include the library in my ino file and call functions within it, all works fine. When I have it linked from one of my class header files, it gives this output:
In file included from C:\Users\Kyle\Documents\Arduino\libraries\OneBitDisplay-master\src/OneBitDisplay.h:4:0,
                 from C:\Users\Kyle\Projects\EOS-OSC\OLED.h:1,
                 from C:\Users\Kyle\Projects\EOS-OSC\OLED.cpp:1:
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:67:1: error: 'uint8_t' does not name a type
 uint8_t iSDA, iSCL; // pin numbers (0xff = disabled)
 ^~~~~~~
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:68:1: error: 'uint8_t' does not name a type
 uint8_t bWire; // use the Wire library
 ^~~~~~~
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:69:1: error: 'uint8_t' does not name a type
 uint8_t iSDABit, iSCLBit; // bit numbers of the ports
 ^~~~~~~
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:70:1: error: 'uint32_t' does not name a type; did you mean 'char32_t'?
 uint32_t iDelay;
 ^~~~~~~~
 char32_t
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:75:10: error: 'uint32_t' does not name a type; did you mean 'char32_t'?
 volatile uint32_t *pSDADDR, *pSDAPORT; // data direction and port register addr
          ^~~~~~~~
          char32_t
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:76:10: error: 'uint32_t' does not name a type; did you mean 'char32_t'?
 volatile uint32_t *pSCLDDR, *pSCLPORT;
          ^~~~~~~~
          char32_t
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:82:26: error: 'uint8_t' has not been declared
 int I2CRead(BBI2C *pI2C, uint8_t iAddr, uint8_t *pData, int iLen);
                          ^~~~~~~
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:82:41: error: 'uint8_t' has not been declared
 int I2CRead(BBI2C *pI2C, uint8_t iAddr, uint8_t *pData, int iLen);
                                         ^~~~~~~
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:86:34: error: 'uint8_t' has not been declared
 int I2CReadRegister(BBI2C *pI2C, uint8_t iAddr, uint8_t u8Register, uint8_t *pData, int iLen);
                                  ^~~~~~~
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:86:49: error: 'uint8_t' has not been declared
 int I2CReadRegister(BBI2C *pI2C, uint8_t iAddr, uint8_t u8Register, uint8_t *pData, int iLen);
                                                 ^~~~~~~
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:86:69: error: 'uint8_t' has not been declared
 int I2CReadRegister(BBI2C *pI2C, uint8_t iAddr, uint8_t u8Register, uint8_t *pData, int iLen);
                                                                     ^~~~~~~
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:92:27: error: 'uint8_t' has not been declared
 int I2CWrite(BBI2C *pI2C, uint8_t iAddr, uint8_t *pData, int iLen);
                           ^~~~~~~
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:92:42: error: 'uint8_t' has not been declared
 int I2CWrite(BBI2C *pI2C, uint8_t iAddr, uint8_t *pData, int iLen);
                                          ^~~~~~~
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:100:1: error: 'uint8_t' does not name a type
 uint8_t I2CTest(BBI2C *pI2C, uint8_t addr);
 ^~~~~~~
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:104:27: error: 'uint8_t' has not been declared
 void I2CScan(BBI2C *pI2C, uint8_t *pMap);
                           ^~~~~~~
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:110:27: error: 'uint32_t' has not been declared
 void I2CInit(BBI2C *pI2C, uint32_t iClock);
                           ^~~~~~~~
C:\Users\Kyle\Documents\Arduino\libraries\BitBang_I2C-master\src/BitBang_I2C.h:115:36: error: 'uint8_t' has not been declared
 int I2CDiscoverDevice(BBI2C *pI2C, uint8_t i);
...

This keeps going for quite a while where any types from the stdint library are referenced.
It seems to only occur when the library is included in a header file, not when it is in the main ino sketch. I have it linked in the ino, knowing that the compiler needs all referenced libraries placed there.
When I remove the include from the header, it gives errors that it can't find types for variables that I've declared (as it should, given that these types are defined in the library I'm trying to include)
Any clues? I've never posted anything on StackOverflow, because I usually can find the answer but this one has stumped me.
I'm happy to provide any other code or debugging output if needed.

In Oled.cpp (or Oled.h), try including Arduino.h before any other includes.

That did it. Thanks. I had them in there, just needed to have Arduino.h before everything else. Makes sense, dependency-wise. Just a bit strange because looking at the source code the libraries already include Arduino.h themselves. Must have to do with the way Arduino searches for dependencies.

The uint8_t and the uint32_t types reported in your compile errors are defined in the stdint.h file. In .ino the stdint.h is included  with Arduino.h (which is added at ino to cpp conversion by Arduino builder).
The BitBang_I2C.h should include Arduino.h or stdint.h, but the author forgot to add it. Then if BitBang_I2C.h is included in .ino, the Arduino.h is included above it and the types are defined, but if you include BitBang_I2C.h in a cpp file which doesn't include Arduino.h or stdint.h, then the stdint defines are missing.
The workaround for this bug is to add #include <stdint.h> at the top of your OLED.cpp file.

Thanks. I had included both Arduino.h and stdint.h, but it looks like I had them out of order. Feels kinda stupid now

Arduino IDE implicitly includes some headers. Especially "arduino.h".
You need to include "stdint.h" into your header files for completeness.


text:
Will the pro trinket gamepad library work on an Arduino Uno?
I have an Arduino Uno and I wanted to know if the pro trinket gamepad library works on an Arduino Uno since both have same atmega328p CPU chip.

why don't you try it? ... then ask a question about any problem that you encounter

I’m not familiar with the pro trinket device (https://learn.adafruit.com/introducing-pro-trinket/pinouts?view=all) but looking at the library (https://github.com/buxit/Pro_Trinket_USB_Gamepad) readme says it is an Arduino library. I suspect it would come down to checking pins and peripherals to decide whether it will work on Uno. @jsotola’s suggestion is practical, why not try it and see? I’d put my money on your having a reasonable chance of success.

The Pro Trinket has a USB connector wired to the ATmega328P, and the
Pro_Trinket_USB_Gamepad library uses this connection to impersonate a
USB gamepad.
The Arduino Uno also has a USB connector, but it is not wired to the
ATmega328P. It is instead connected to an auxiliary chip (an ATmega16U2)
which serves exclusively as a USB-to-serial converter. Since your
sketches run on the 328P, and the 328P has no access to the USB port,
you cannot use this library on the Uno.
Well, actually you may be able to use the library if add an extra USB
connector, and link it to the 328P. See how it is done in the schematic
of the Pro Trinket 5V. Beware of the 3.6V Zener diodes:
these are needed to avoid damaging the serial port of your computer.


text:
Could I put an arduino in series with a battery charger?
recently in one of my projects I have wanted to make battery powered. I was wondering if I could connect the charger to the battery and the battery to the Arduino without blowing it. The battery is 12v 7.2 Ah and the charger is 12v 1 A.
(See attached)

Please explain in more detail what you have and what you want to do. You can also draw a schematic do be more clear.

I added the picture. Do I need something like a diode or just wire everything together like the image?

Just for clarity: your diagram shows the Arduino, the batteries, and the charger connected in parallel - which is correct for what you want to do. However, a 12v power supply (batteries, charger, or both) are at, or very close to the maximum input voltage spec the Uno. The Uno's voltage regulator has to waste - as heat - a good deal of power in reducing the voltage to 5v. And if the power supply provides any more than 12 volts, it will exceed regulator's spec.
Update:

how much do you think it would go over?

We can't know without knowing the specs on the particular batteries and charger. A battery charger has to apply a higher voltage than the present voltage of the battery it is trying to charge, in order to drive current into the battery against its (the battery's) voltage. You need to know more about the charger and the batteries.
Update 2:

The batteries are 12V 7.2 Ah and they are PK12V7.2 as the product name.

Those Lead/Acid cells. I didn't find a spec for the charger, but  in automotive use, Lead/Acids are charged at 14.2 volts. Your Uno's regulator won't like that. I'm guessing you measured your charger's output voltage with no load.
Try measuring it with the batteries attached and at low, medium, or almost fully charged. That should give you a better idea. We can only guess without the specs but it sounds like these components would be pushing your Uno's regulator pretty hard.
If these components and the Uno part of a system that requires 12v for some other components, I'd suggest using 2 power supplies, 12v for the components that need it, and 7 volts into Vin (or 5v, if well regulated, into the 5v pin) on your Uno. The lower voltage could be supplied by a buck converter powered off of the 12v, which would fairly efficient and require only one charger.

If it was 12v how much do you think it would go over? The Arduino should take 12v. Do you think there might be any other issues other than the one? The diagram is what I want with 2 batteries and the charger on for a day every two weeks.

The batteries are 12V 7.2 Ah and they are PK12V7.2 as the product name. The charger is the Motomaster 12V 1A lead acid battery charger.

The battery charger charges the batteries but is only 11-12 volts on my multimeter. Any other issues that can hurt the arduino like... something?

11-12V is much too low for charging a Lead Acid battery. This is bad for your battery and it will probably not hold a charge for long, if you do not charge it to 13.8V (at a minimum) to 14.2V or more soon. Reducing 12V down to the 5V the Arduino needs using the standard on-board linear regulator will waste most power going into the board in the form of heat. This is not only very inefficient but can also overheat the regulator. Use a (much more efficient) buck regulator to regulate the 12V down to 7V (Vin) or 5V.

Thank you. Seems like I need a regulator and a new battery charger because even with a load it stays at 12V.


text:
How to set the eeprom initial value when flashing an ESP32
As I use the EEPROM to persist data such as for provisioning the WiFi (SSID and password), I'd like to make sure that the very first time the ESP32 runs, it finds the initial '\0' for the SSID so that it does not run into the WiFi connection code block.
For this I need to set the initial values into the EEPROM when I flash the firmware.
I use platform IO.
How to do that?

You're probably better off using SPIFFS and a "eeprom.bin" file. The current partition scheme of the ESP doesn't provide a dedicated partition for the arduino-like eeprom and the ESP32 doesn't have an EEPROM...

you can set/wipe SPIFFS with default files when uploading.

first of all, the esp32 remembers the WiFi credentials by itself. you don't have to store it. example https://github.com/jandrassy/lab/blob/master/ConfigurationAP/ConfigurationAP.ino

The ESP32 does not have a real EEPROM; instead, the data is stored in the external flash in the non-volatile storage (NVS) partition. The problem is, that the structure of this partition is proprietary. Only the SDK knows "where to find what" within NVS and any access to this partition is done using the SDK.
Unfortunately, the EEPROM.h library uses the NVS partition to store its values.
As the way how data is stored within NVS is closed source, you can't build a flash image that is guaranteed to work in different sketches or different versions of the SDK.
So, if you need to upload pre-made non-volatile data, the EEPROM.h library is practically useless.
A convenient alternative is to put that data in a file and store that file in a filesystem like SPIFFS.h.
This way, you define how data is stored/accessed yourself, so it's much less likely you run into problems when the core experiences changes.
Data upload is straight forward using esptool.py.


text:
Wiring multiple LCD displays to Arduino
I have multiple LCD displays and one Arduino and I just want to show some text on each display separately.

Is it possible to Wiring multiple LCD Displays for the single Arduino board?
Or maximum how many display can I connect one single Arduino?

For HD44780 based displays all the data, register select and read/write pins can be shared. A display only exists at the moment the E pin is toggled. They are designed to share a microprocessor's data bus.
So if you have 50 displays then you can (theoretically, see "fan out" below) run them from 50 "E" pins plus 6 (or 10 depending on if you want to run in 4 or 8 bit mode) shared pins.
Here's an example with 2 displays in 4-bit mode - just replicate for more:

simulate this circuit – Schematic created using CircuitLab
Note: power, ground and contrast connections omitted for brevity.
As you can see the LCDs share all their pins except the E pin. A third display will connect to the same pins, except its E pin would be unique.
Fan out
Fan out is an important concept in digital electronics. An IO pin can only deliver a certain amount of current and each device a pin connects to adds "load" to that pin. Too many devices and the IO pin will struggle to control the devices properly.
To combat this a "bus transceiver" (such as the 74HC245) is commonly used. If one IO pin is capable of driving, for the sake of argument, 5 devices, and one bus transceiver is also capable of driving 5 devices then the IO pin could drive 5 bus transceivers giving you control over a potential 25 devices.


text:
7-Segment Display w/ Potentiometer
(Backstory) So, I took an computer engineering class in high school (grade 11 level), where I learned a bit about breadboarding as well as arduinos (I would like to stress a bit). It has been 5 years, and I don't remember much; but the other day my little brother started taking the same class. He has the following assignment, which I have also endeavored to try for fun:
(Not Backstory) I need to make a potentiometer control a 7-segment display so that it displays a number (0-9) based on the potentiometers value. I hopped on to tinkercad to test stuff out before acuatally doing anything, and I came up with the following real quick:

I've tested the above model and I know it works, but the following code does not work.
int a = 2;
int b = 3;
int c = 4;
int d = 5;
int e = 6;
int f = 7;
int g = 8;
int potentiometer = 9;

void setup() {
  for(int pins = 2; pins <=8; pins++){
  pinMode(pins, OUTPUT);
 }
  pinMode(potentiometer, INPUT);
}

void loop() {
  int pRes;
  pRes = analogRead(potentiometer);
  if (pRes >=0 && pRes <=101){
    //0
    digitalWrite(a, LOW);
    digitalWrite(b, LOW);
    digitalWrite(c, LOW);
    digitalWrite(d, LOW);
    digitalWrite(e, LOW);
    digitalWrite(f, LOW);
    digitalWrite(g, HIGH);
    }
  else if (pRes >=102 && pRes <=203){
     //1
    digitalWrite(a, HIGH);
    digitalWrite(b, LOW);
    digitalWrite(c, LOW);
    digitalWrite(d, HIGH);
    digitalWrite(e, HIGH);
    digitalWrite(f, HIGH);
    digitalWrite(g, HIGH);
    }
  else if (pRes >=204 && pRes <=305){
     //2
    digitalWrite(a, LOW);
    digitalWrite(b, LOW);
    digitalWrite(c, HIGH);
    digitalWrite(d, LOW);
    digitalWrite(e, LOW);
    digitalWrite(f, HIGH);
    digitalWrite(g, LOW);
    }
  else if (pRes >=306 && pRes <=407){
    //3
    digitalWrite(a, LOW);
    digitalWrite(b, LOW);
    digitalWrite(c, LOW);
    digitalWrite(d, LOW);
    digitalWrite(e, HIGH);
    digitalWrite(f, HIGH);
    digitalWrite(g, LOW);
    }
  else if (pRes >=408 && pRes <=509){
    //4
    digitalWrite(a, HIGH);
    digitalWrite(b, LOW);
    digitalWrite(c, LOW);
    digitalWrite(d, HIGH);
    digitalWrite(e, HIGH);
    digitalWrite(f, LOW);
    digitalWrite(g, LOW);
  }
  else if (pRes >=510 && pRes <=611){
    //5
    digitalWrite(a, LOW);
    digitalWrite(b, HIGH);
    digitalWrite(c, LOW);
    digitalWrite(d, LOW);
    digitalWrite(e, HIGH);
    digitalWrite(f, LOW);
    digitalWrite(g, LOW);
    }
  else if (pRes >=612 && pRes <=713){
    //6
    digitalWrite(a, LOW);
    digitalWrite(b, HIGH);
    digitalWrite(c, LOW);
    digitalWrite(d, LOW);
    digitalWrite(e, LOW);
    digitalWrite(f, LOW);
    digitalWrite(g, LOW);
    }
  else if (pRes >=714 && pRes <=815){
    //7
    digitalWrite(a, LOW);
    digitalWrite(b, LOW);
    digitalWrite(c, LOW);
    digitalWrite(d, HIGH);
    digitalWrite(e, HIGH);
    digitalWrite(f, HIGH);
    digitalWrite(g, HIGH);
    }
  else if (pRes >=816 && pRes <=917){
    //8
    digitalWrite(a, LOW);
    digitalWrite(b, LOW);
    digitalWrite(c, LOW);
    digitalWrite(d, LOW);
    digitalWrite(e, LOW);
    digitalWrite(f, LOW);
    digitalWrite(g, LOW);
    }
  else if (pRes >=918 && pRes <=1023){
    //9
    digitalWrite(a, LOW);
    digitalWrite(b, LOW);
    digitalWrite(c, LOW);
    digitalWrite(d, HIGH);
    digitalWrite(e, HIGH);
    digitalWrite(f, LOW);
    digitalWrite(g, LOW);
    }
}

Can someone explain to me what I've done wrong (and offer corrections)?

In what way does it "not work"?

I think you wired the potentiometer incorrectly. The middle pin goes to an analog input pin (you used a digital pin on one of the outer pins), the outer pins to ground and 5V respectively.

i see no debugging code ... how do you know that the pot is being read as expected?

Only the pins with labels starting with “A” (A0 through A5 on the Uno)
can be used as analog inputs.
The pin of the potentiometer that is currently not connected has to
be connected to 5V.

Thanks for the help, can't believe I overlooked something like that.

Also I switched HIGH and LOW lol


text:
Serial.parseInt works for first menu but now in a sub menu
I am trying to use the Serial object to print some lines giving the users some options to select by entering an int. It works at this main menu. But when the user selects 1 I use Serial again to print some lines and collect another int. But in this submenu it prints the line, waits a second and then continues back out to the main menu. Below is my entire sketch:
int menu = 0;

void setup() {
  // put your setup code here, to run once:
  //Starting the serial comm
  Serial.begin(115200);
}

void loop() {
  // put your main code here, to run repeatedly:
  if (menu == 0) {
    //Prints the menu to the serial port
    Serial.println("Select an option:");
    Serial.println("-----------------");
    Serial.println("1) Do Submenu");

    menu = getSerialInt();
  }

    //Used to calibrate the pen height
  if (menu == 1) {
    int calibrating = 1;
    while (calibrating == 1) {          //While loop that will continue until "0" is sent in the serial port
      Serial.println("Enter a pen value: ");
      int penMove = getSerialInt();

      Serial.println("You entered: ");
      Serial.println(penMove);
      if (penMove == 0) {
        calibrating = 0;
      }
    }
    menu = 0;   //Sets the menu variable back to 0
  }
}

int getSerialInt() {
  int retInt;
  Serial.flush();

  while (!Serial.available()) {}  //Waits for an input on the serial device
  retInt = Serial.parseInt();       //Takes the Serial input and looks for an integer
  Serial.flush();

  return retInt;
}

Thanks in advanced for any help trying to debug this.

Based off this thread: https://forum.arduino.cc/t/parseint-clears-serial-available-but-leaves-terminator-in-serial-buffer/515199/8
And some other threads talking about carriage returns, I rewrote getSerialInt to call parseInt() twice to trow away the carriage return:
int getSerialInt() {
  int retInt;
  Serial.flush();

  while (!Serial.available()) {}  //Waits for an input on the serial device
  retInt = Serial.parseInt();       //Takes the Serial input and looks for an integer
  Serial.parseInt(); // throw away carage return
  Serial.flush();

  return retInt;
}

There is probably a better way to do this...


text:
Pressed Buttons are permanently low and one of them is not working
I am a beginner to Arduino, and I'm having a problem in a project that I am currently working on.
I was just beginning to write the code, after preparing the components and the wiring, and suddenly two of my buttons never stopped outputting, despite my instructions to only output when the buttons are low, and the other one doesn't do anything at all.
I am using three buttons, one of them is a interruptor switch.
Here is my code:
#include <Adafruit_NeoPixel.h>

#define PIN 3    // input pin Neopixel is attached to
#define NUMPIXELS 28 // number of neopixels in strip

#define TRAVAO 8
#define PISCA 13
#define QUATRO_PISCAS 11

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

int redColor = 0;
int greenColor = 0;
int blueColor = 0;

void setup() {
  pixels.begin();

  pinMode(TRAVAO, INPUT_PULLUP);
  pinMode(PISCA, INPUT_PULLUP);
  pinMode(QUATRO_PISCAS, INPUT_PULLUP);

  Serial.begin(9600);
}

void loop() {
  if(digitalRead(TRAVAO) == LOW) {
    Serial.print("bbb");
  }

  if(digitalRead(PISCA) ==  LOW) {
    Serial.print("ccc");
  }

  if(digitalRead(QUATRO_PISCAS) ==  LOW) {
    Serial.print("ddd");
  }

  delay(1);
}

Here is my arduino:

I count 42 "pixels" and the code says #define NUMPIXELS 28 So, I'm wondering how accurate the diagram is to the project. Are there actually 42? Is it really an UNO? etc.

What happens if you use only the four-LED strip?

@timemage only 28 are currently wired and being used. The six interior pixels of each circle are not being used.

@timemage nothing changes.

buttons never stopped outputting, despite my instructions to only output when the buttons are low ... maybe the buttons are always low

@jsotola could you please clarify?

maybe the input pins on the arduino are pulled low when the buttons are not pressed ... did you disconnect the wires to the arduino pins to confirm that the program stops printing to serial?

Make sure your buttons are oriented correctly, not turned 90°.

An in focus well lit picture of your actual wiring may help.

i think the slider PISCA not need INPUT_PULLUP
pinMode(PISCA, INPUT_PULLUP);
just pinMode(PISCA, INPUT_PULLUP);

Here's your problem:
#define TRAVAO 8

As you can see from your wiring diagram, nothing is connected to pin 8.


text:
atTiny85 5V and servo usage
I have an AtTiny85 that I would like to move a servo on I/O "4" for this project.
I can't seem to get it to work, no matter what I do. I had tons of issues getting it to program, but I've gotten it to a place where it will program a blink, and it will also blink the LED in the circuit diagram in the link provided. I have the servo wired, and I'm pretty darn sure the wiring is correct (when are we 100% sure?). I've tried these programs to no success:
// Trinket Servo Monster sketch
// Hardware: Adafruit Trinket (3V or 5V), micro servo, LED + resistor
// Libraries: uses Adafruit_TiCoServo library to manage servo pulses,
// even though NeoPixels are NOT being used here.

#if !defined(__AVR_ATtiny85__)
 #error "This code is for ATtiny boards"
#endif
//#include <Adafruit_TiCoServo.h>
#include <ServoManager.h>
#include <avr/power.h>

// Servo parameters.  Pin MUST be 1 or 4 on a Trinket.  Servo position
// is specified in raw timer/counter ticks (1 tick = 0.128 milliseconds).
// Servo pulse timing is typically 1-2 ms, but can vary slightly among
// servos, so you may need to tweak these limits to match your reality.
#define SERVO_PIN  4 // Pins 1 or 4 are supported on Trinket
#define SERVO_MIN  4 // ~1 ms pulse
#define SERVO_MAX 26 // ~2 ms pulse

#define LED_PIN    0 // "Eye" LED is connected here

PrecisionServo* servo;

void setup(void) {
  ServoManager::setup(1);
  servo = ServoManager::createServo(4);
  //servo->setSetting(SERVO_MEDIUM_ENDPOINT);

//#if (F_CPU == 16000000L)
  // 16 MHz Trinket requires setting prescale for correct timing.
  // This MUST be done BEFORE servo.attach()!
//  clock_prescale_set(clock_div_1);
//#endif
  //servo.attach(SERVO_PIN);
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, HIGH);
}

uint32_t lastLookTime = 0; // Time of last head-turn

void loop(void) {

  //unsigned long t = millis(); // Current time

  // If more than 1/2 second has passed since last head turn...
  servo->setTarget(0);
  ServoManager::waitUntilFinished();

  servo->setTarget(180);
  ServoManager::waitUntilFinished();

  // Unrelated to head-turn check,
  if(random(10) == 0) { // there's a 1-in-10 chance...
    // ...of an "eye blink":
    digitalWrite(LED_PIN, LOW);  // The LED turns OFF
    delay(random(50, 250));      // for just a short random moment
    digitalWrite(LED_PIN, HIGH); // then back ON
  }

  //delay(1000); // Repeat loop() about 10 times/second
}

SO I scaled back and just tried to write a high out as follows:
void setup() {
  pinMode(4, OUTPUT);
}

void loop() {
  digitalWrite(4, HIGH);
  delayMicroseconds(1000);
  // 1 millisecond determines the servo going forwards
  digitalWrite(4, LOW);
  delay(19);
}

But this didn't work either.
Shouldn't the servo move with just a write to 'high' and 'low'?

no it should not, not a hobby servo ... there are many tutorials on the web about the operation of hobby servos and how to control them

Can you link? Nothing I've found so far has helped.

https://duckduckgo.com/?q=arduino+hobby+servo&ia=web

The servo requires a PWM signal to the control lead to move.
This datasheet kind of bears that out...
http://www.datasheetcafe.com/sg90-datasheet-pdf-9-g-micro-servo/


text:
Drivers for CH9102X serial port chip
Some ESP-family cheap boards manufacturers had recently moved to CH9102X serial port chip (from CP2102), and it seems the drivers for CH9102X are hard to find.
Where can I download them?

It can be found on manufacturer's website: http://www.wch.cn/search?q=CH9102&t=downloads
Please note, that some drivers' downloading pages are only available in Chinese, so make sure you open Chinese (not English) site version.
Windows CDC driver: http://www.wch.cn/downloads/CH343CDC_ZIP.html
Windows SER driver: http://www.wch.cn/downloads/CH343SER_ZIP.html
MacOS driver: http://www.wch.cn/downloads/CH34XSER_MAC_ZIP.html
P.S. For Windows 7 x64 I recommend using the first one (CDC). SER driver didn't work for me because of signing issues.

Did you ask this question just so that you could answer it?

Exactly. See also: https://stackoverflow.blog/2011/07/01/its-ok-to-ask-and-answer-your-own-questions/