text:
Want to create bluetooth audio control (volume up/down, play, pause, etc.) for smartphone
I want to create a bluetooth remote audio control to control smartphone audio, essentially identical in function to this type of equipment:

https://www.amazon.com/FAVOLCANO-Bluetooth-Button-Smartphone-Samsung/dp/B01C5E95XG/ref=pd_lpo_147_bs_t_1?ie=UTF8&refRID=1GRBCPDRMD9YPYPGK73Y
This device is simply a bluebooth remote control which allows you to play or pause audio, skip forward or backward and change media volume on the smart phone.
All of the Arduino tutorials I see are about either using the iPhone to control a bluebooth device, or about using bluetooth to control an arduino, neither of which are what I want to do.
Can you point me in the right direction?

You need a BLE shield with library support for acting as a Bluetooth HID device.

@Majenko Thank you!  It's the library that needs bluetooth HID support, not the shield, correct?  Or do both need to support it?

Both need to support it.

AVRCP is usually used by Bluetooth remotes, not HID. Not sure if BLE supports AVRCP though.

@IgnacioVazquez-Abrams - Is HID is normally for non-audio purposes?  I don't think it matters to me its BLE or not - it's more just a matter of whether I can accomplish my purpose.  Is there a way to (by looking at diagnostics etc) to see if an individual device (eg the one in the pic above) is AVRCP and/or BLE?

They're all AVRCP. I have a remote that also does HID, but that's for the camera trigger; the audio controls are still AVRCP.

Bluetooth supports multiple protocols for multiple purposes.  There is low latency low quality monorail bi-directional communication with a little bit of bandwidth for control for Bluetooth phone calls.  This is called HFE Bluetooth protocol.  If you are interfacing a keyboard or a mouse you would use the Human Interface Device protocol or HID.  If you wanted to listen to music and control it's playback you would use the high latency high quality 2 audio sending channels (stereo) no return audio channel with a little bit of bandwidth for controlling playback called Advanced Audio Distribution Profile or A2DP.
In this specific case we are only interested in controlling playback.  So we could use the HID Bluetooth protocol.  However, the native music players on the platform you are using (Android or iPhone) likely will not be listening to such a device.  In order for this to work you will probably have to write your own Android or iPhone music player.
On the other hand, it is likely the native music players will work with A2DP Bluetooth protocol.  Unfortunately, it is also suspected that once the A2DP Bluetooth connection is established, the phone's speaker will be shutdown and all audio will be diverted to the Bluetooth connection.
Finally, there is the Audio/Video Remote Control Profile or AVRCP.  This protocol is used to control media playback.  There are several versions of this protocol so what features are available for a given device / music-application may vary greatly.

+1 nice answer. I do have one thing to add. I've tested media control via HID and it works for me on Android. (Perhaps HID support has improved in the past 2.5 years.) It's easy enough to test using a bluetooth keyboard that has media buttons. HID may be easier to implement, but I found one drawback. If I haven't hit a key after several minutes, there is a delay in processing the next key. (Power saving mode?) One of my goals was to skip podcast commercials, the delay made HID less useful for this purpose. AVRCP a better choice, even if it's harder to get working.

Thanks for the +1.  Assuming the devices you are using are powered off of batteries, I wonder if the delay can be avoided if devices were powered off main instead.

I didn't spend the time to dig into this, I only made some assumptions about the delay. I tested with a BT keyboard, not a device I programmed. The keyboard would go into a stand by mode presumably to save power. This indicated to me that maintaining a full connection used too much power, and behavior seemed to be driven by the keyboard because it was documented in its user manual After that I looked at at AVRCP. But now I'm reading up on BLE's HID over GATT Profile, HOGP which has been supported by Android since KitKat. It's looking like the right solution for me.

I can add something to @st2000's excellent answer (in a better format than our discussion in the comments there).
The original question is vague. Does Bluetooth mean Classic or is Low Energy (BLE) acceptable or preferred. Which smartphones must be supported? Apple and/or Android? And what minimum version must be supported?
The 2.5 years that have passed since this question was asked makes it easier to choose BLE because adoption is so prevalent now.
I've been researching what it would take to implement a media control device as described in the original post. My target smartphone is Android Nougat. My goal is to skip podcast commercials. I have tested using a Bluetooth Classic keyboard. The media control buttons, Play/Pause, skip forward, skip back, etc. seem to do what I need.
I'd prefer to use BLE's support for keyboards and other Human Interface Devices: HID over Gatt Profile (HOGP). The KitKat release notes say that's when HID over GATT support was added, so it's been around for a while.
Having decided on a Bluetooth LE profile, device selection remains. Adafruit Bluefruit LE UART Friend has a HIDKeyboard example. I prefer an MCU with integrated BLE support. While total overkill for this application, I have an ESP32 that I plan to use for this. It has good community support and is cheap. If battery life (or size) becomes a problem, I'll look for a lesser device.

I did it on HC-05 (reflash to RN-42) and use HID profile to send command: Play/pause fwd/rwd vol+/-
I can post sample code if needed.
Here's the video https://youtu.be/y8PcNbAA6AQ

Please edit your answer to add the sample code.

I'm trying to do exactly the same, would you mind sharing your code please?

Yes, some sample code would be much appreciated.

Posting Arduino code that shows how to use the AVRCP would be great, if you've done it.


text:
Sending commands to an STM32 chip via UART with Arduino Pro Mini
I am having trouble making an Arduino Pro Mini send commands via USART to an STM32 chip. The serial communication protocol is currently set to 9600 baud rate with no flow control or stop bits. Is there anything special that has to be done to make these two devices communicate with each other? I'm using the standard RX/TX pins for this. The Arduino logic level is 3.3V. The STM32 logic level is 2.5V. They share a common ground. I should also note that there is a 1K ohm resistor in series with each data line. Here's the code that I'm trying to use:
#include <Arduino.h>

void setup()
{
  Serial.begin(9600);
  delay(4000);
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop()
{
  digitalWrite(LED_BUILTIN, HIGH);
  delay(1000);
  digitalWrite(LED_BUILTIN, LOW);
  delay(1000);
  digitalWrite(LED_BUILTIN, HIGH);
  delay(1000);
  digitalWrite(LED_BUILTIN, LOW);
  delay(1000);
  String voltage = String("85 2 0 0 10 174 96"); //Command to set voltage output on STM32
  Serial.println(voltage);

  while (1) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(200);
    digitalWrite(LED_BUILTIN, LOW);
    delay(200);
  }
}

Nothing special needs to be done. Beyond that, we can't really help you without seeing some code.

Do the chips share a common ground? Do they use the same logic voltage levels? Are they both powered? Did you connect the Arduino's TX to the STM32's RX? Do you have a scope?

Please see the edited post. They are both definitely powered and the RX/TX lines are wired correctly.

I see nothing wrong on the Arduino side. Are you sure the STM32 expects text rather than binary? Does it like the CRLF line termination? Is its RX 3.3V-tolerant?

According to the datasheet, the STM32 is 3.3V tolerant. I haven't tried binary. I will give that a go. Thank you for the quick response!

What is your stm code and why is it powered at 2.5V?

Just a quick note: confirm that the STM is 3.3V tolerant even when Vcc is 2.5V; this is because most of the times the upper value is Vcc+0.3V. Even though, I'm confident it is compatible with the voltage range.

Moreover, check with an oscilloscope on the serial line, so that you can detect whether the issue is with the arduino or the STM

Unfortunately, I don't have access to the STM code. I added a voltage divider to the Arduino TX to bring it down to 2.5V. I tried transmitting binary code with no luck. Is it possible that I need to convert the values in the string to ASCII characters since it's USART? I will take a look with an oscilloscope when I try again.

I finally figured it out! I ended up having to declare the values in the string as integers, and then I used serial.write() instead of serial.print(). Thank you everyone for your help!

source: Stack Exchange

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

sort: votes


text:
How to Read ADC value without Common GND ? (Possible or not !)
I want to Read external signal with the microcontroller.
But the problem is that ADC does not work because the signal GND and the microcontroller are not Common,
My question is, have you encountered such a problem? Is there a way to do it?

you are trying to measure the voltage difference between two nodes with only one node attached ....... try measuring the voltage of a battery with only one probe

How about You can explain more ? @jsotola

jsotola means: You need a common ground, no way around that. So connect both grounds together

So there is no solution. I tried to read one of the ECG electrode signals to the ADC until I had trouble. @chrisl

you could use an opto coupler if needed. i've DIY'd "analog" ones with an LED glued to a CDS then wrapped in tape, adjusting the LED resistor to "calibrate" the range. After tweaking, i was able to get a fairly linear response throughout 75% of the range.

The solution is to always use at least 2 electrodes. You need 1 electrode, that you connect to ground. You can put this electrode to somewhere neutral (this instructable suggest connecting it to your leg, but I don't know, if that position is really good).
An ADC measures voltage and voltage is the difference in potential between 2 points, so to measure voltage you by definition need 2 points/connections.

Note: The voltages from the EEG electrodes are normally very low, so that they completely vanish in the noise. To really get something useful, you need to amplify the signal. I think there are many tutorials out there, that explain how to do this.

This is true . But I want to send each 10 leads wirelessly. I need to read each of the leads with ADC.
Can the microcontroller ground be common with the shield lead ground to work the ADC? @chrisl

There are many things unclear in that question. What shield? (You didn't mention a shield before) And how do you plan to "send leads wirelessly"? An analog voltage cannot just simply send wirelessly. The normal way is to measure it wired (since you need it wired for measurement), and then send the measured value over a wireless transmit technology of your choice. Do you already have a complete project plan? If yes, you need to share it for me to answer. If no, then you first need to think about the overall plan. How everything should be working

OK . Let me explain the project to you. I first wanted to wire 10 leads of ECG each with #WiFI sended. But because the ECG device works differently, it didn't work !!!!So I wanted to put all the leads in a small control panel and send it with #WiFI.
I'm confused now and I don't know what to do.
What do you think should be done? @chrisl

"But because the ECG device works differently" Do you already have some kind of device, that does the actual measurement of the ECG? Or do you have to build one? It is unclear to me, what you already have. You seem to need general project guidance. Unfortunately this site is not good for guidance, since it's  a simple Q&A site. Maybe you get better results and help for your project when posting in the project guidance section of the Arduino forum (you can simply google it). A forum is a better fit for project guidance.

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


text:
Timing 12 relays
I need a simple code to turn on 12 outputs one after another 2 seconds apart. A pushbutton will initiate this and the outputs will stay on for 3 minutes at which time all outputs will turn off awaiting the pushbutton input
So far:
Void setup
pinMode (10,output);
PinMode (11,output);
PinMode (12,output);

Void loop
delay(100);
digitalWrite (10,HIGH);
delay (2000);
digitalWrite(11,HIGH);
delay(2000)
digitalWrite(12,HIGH);

delay(180000);
digitalWrite (11,LOW);
digitalWrite (12,LOW);
digitalWrite (10,LOW);
exit(0);

Push remote reset button to restart.
Only tried 3 outputs for now and haven’t tried “Crossroads” code yet but I will.

you cannot do that without hardware ... and all hardware is not the same ... so i think that you forgot include all of the information

you avoided a downvote from me because you explained the desired functionality very clearly ... you can use that clear description and turn it into code ... simple loop with an incrementing pointer and a 2 second delay ... 2 minute 58 seconds delay after loop finishes ... then all off and back to begining

turning a relay on is no different than turning on an LED, so start writing the code. functions you gonna need mainly is delay(), pinMode() and digitalWrite(). after finishing the prototype using LEDs replace the LEDs with a NPN transistors like a 2N2222 to turn on relays. don't connect relays directly to arduino...

What have you tried so far?

@newbie, NO, not delay(). That is a dead-end. You, and the OP, need to search on "blink without delay explained" and read the resulting article.

@DuncanC yes delay() is a "code-blocking" function but easier to use than millis() that's why i suggested delay() function...

delay() is easier to use for dirt-simple sample code. The minute you go beyond the absolute simplest goal, it becomes a blocker that prevents you from accomplishing your task and you have to rip out the delay-based code, go study the "BlinkWithoutDelay" example, and learn how to use millis() to do cooperative multi-tasking. Except in VERY limited circumstances delay() is a dead end that teaches bad habits.

Once my DuPont cables arrive I can connect the relay module to the Arduino. I should have mentioned about the relays earlier. I’m obviously new at this where as you guys have been around the block a few times. I’m pretty sure that once I go through your suggestions I can come up with a plan. Thanks

Don't use Delay. CrossRoads provided a decent starting point for your code, but his code is based on delay(), which is a dead end.
Instead of delay, use a bool running to track whether you're relay sequence is running or not. Also have an unsigned long startTime, and an array of bools to track if each relay is on or off.
If !running, check the button. If the button is pressed, set running to true, and set startTime to millis().
Then, use millis() to figure out where you are in the sequence. Calculate (millis()-startTime)/1000/num_relays. Let's call it relayIndex.
When relayIndex is less than num_relays - 1, check the bool for that relay, and if it's off, set it on and turn on that relay. When relayIndex reaches num_relays-1, you're done turning on relays. Now it's time to wait for 3 minutes to go by. After 3 minutes, turn off all the relays and relay bools, and set running=false. Have the reset button do the same thing.
EDIT
Also note that controlling relays from an Arduino (or from other solid state devices for that matter) requires special hardware and precautions. You should probably use a "digital" relay (something like this, or better yet this 6 channel relay) that isolates the Arduino control line from the high current needed to drive the relay.
Failing that, you should build a control circuit from a MOSFET transistor and a "flyback diode". Without flyback diodes, the inductive coils on your relays emit "back EMF" which will likely fry your transistors (and possibly the Arduino)

I particularly liked the fact that you did not provide a complete working solution, but rather pointers for the OP to write his own code.. +1

Yup. I don't like to provide code to beginners. I think it's counter-productive. More often than not they copy/paste it into their program, complain if there are minor compile errors, and don't really gain any understanding. By outlining a solution and supporting the OP they actually learn.

While I agree you shouldn't give a complete working solution; I do think this source (https://www.forward.com.au/pfod/ArduinoProgramming/TimingDelaysInArduino.html) will help to atleast get an understanding of the possible implementation.

Simple code:
byte buttonPin = 2;
byte relayPins [] = {3,4,5,6,7,8,9,10,11,12,13,14,};
byte x;

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
  for (x=0; x<12; x=x+1) {
    pinMode(relayPins[x], OUTPUT);
  }
}

void loop() {
  if (digitalRead(buttonPin) == LOW) {
    for (x=0; x<12; x=x+1) {
      digitalWrite(relayPins[x], HIGH); // drive base of NPN or N-MOSFET to sink current
      delay(2000);
    }
    delay(180000); // dumb 3 minute delay
    for (x=0; x<12; x=x+1) {
      digitalWrite(relayPins[x], LOW);
    }
  }
}

And of course, supporting hardware to drive relay coils.

The Arduino will not sense your button presses because, most of the time, it will be busy delaying when you press the button.

There is no requirement to do anything else after the start button is pressed, so a dumb delay in this instance will provide the control needed.  In general, blink without delay style timing would be better.

Sorry, my comment was wrong: I was mislead by your poor indentation (and missing braces) and didn't notice the delay() was within the if. I fixed your code formatting to make the intent clearer.

This code will miss button presses most of the time while running a relay sequence because it will spend the vast majority of its time in one of the 2 delay statements. A reset button wouldn't work very well, and would not stop the 3 minute period while all the relays are active (unless you press the hardware reset button and reboot the Arduino.)

Is there any requirement to do anything else for (2 seconds * 12) + 3 minutes?  No. So let the delay whining go already.

I'm not whining. I'm pointing out a severe limitation of the approach you are suggesting. I've been bitten several times by writing some Arduino code where I think "it doesn't matter, I don't need to handle more than one thing at a time - delay() is fine!" and then expanded my project to the point where using delay() is a total blocker for what I need to do next, and then had to go back and rewrite substantial chunks of code with very different logic.

It's a bad habit to use that approach because it only works in the most trivial of cases, and if you start out with delay() and move beyond the trivial to doing anything of any complexity, you have to throw out your delay-based code and rewrite it. The logic flow of using millis() is different, so it can be a painful rewrite. I speak from experience.


text:
Not receiving messages from Gsm sim900
I'm getting message as "Message sent" in laptop but not receiving the same message in mobile phone
Gsm module I'm using is Sim900
And the code I used is below
#include <SoftwareSerial.h>

// Define RX and TX pins for SoftwareSerial
SoftwareSerial mySerial(7, 8); // RX, TX

void setup() {
  // Start hardware and software serial communication
  Serial.begin(9600);       // Serial monitor communication
  mySerial.begin(9600);     // GSM module communication

  // Give time for GSM module to initialize
  delay(1000);

  Serial.println("Initializing GSM Module...");
  mySerial.println("AT"); // Send AT command to check communication
  delay(1000);
  showResponse();

  // Set SMS mode to text
  mySerial.println("AT+CMGF=1");
  delay(1000);
  showResponse();

  // Set recipient phone number and message
  String phoneNumber = "+919663781942"; // Replace with recipient's phone number
  String message = "Hello! This is a test SMS from SIM900.";

  // Send SMS
  sendSMS(phoneNumber, message);
}

void loop() {
  // Keep listening for GSM responses
  if (mySerial.available()) {
    Serial.write(mySerial.read());
  }
}

void sendSMS(String number, String text) {
  Serial.println("Sending SMS...");

  // Send AT command to specify recipient
  mySerial.print("AT+CMGS=\"");
  mySerial.print(number);
  mySerial.println("\"");
  delay(1000);
  showResponse(); // Show response to confirm if number was accepted

  // Send the message text
  mySerial.print(text);
  delay(1000);

  // End SMS with CTRL+Z (ASCII 26)
  mySerial.write(26);
  delay(5000); // Wait for the message to send

  showResponse(); // Show response from the GSM module
  Serial.println("SMS Sent!");
}

void showResponse() {
  // Print GSM module response to the serial monitor
  while (mySerial.available()) {
    char c = mySerial.read();
    Serial.print(c);
  }
}

where are you seeing the Message sent message? ... your code does not contain the text Message sent


text:
Improve SD logger - 0.02% of data isn't logged at desired rate
I'm working on a project to read data over CAN, display it on LCD and log data to SD card. LCD is on HSPI and SD card on VSPI. CAN and LCD code is working on core 1 and SD on core 0, there's no wifi. It's all working pretty well but now I'm looking for further improvements. I set the log to 20 Hz and took a sample of 117024 lines. Below is the "uniq -c" output of the seconds that weren't logged at 20 Hz (left column is the actual rate and right column is a specific second in the log). So only 21 out of 117024 lines. But why does this happen and how can I make sure that every line is logged at 20 Hz?
     18 3195
     17 5393
     16 5401
     16 1622
     14 5397
     14 1628
     14 1625
     14 1624
     13 5400
     13 5398
     13 5396
     13 5395
     13 5394
     13 1626
     12 1631
     12 1630
     12 1627
     12 1623
      8 5399
      8 1629

float timeStamp;
char filenameBuffer[23];
String filename;
bool logStarted = 0;
uint32_t lastSyncTime = 0, logStartTime = 0;

File file;

void initSD()
{
    if (SD.begin(5, SPI, 80000000))
    {
        Serial.println("Card Mount OK");
        updateFromFS(SD);
        generateFileName();
        sdInitialised = true;
    }
    else
    {
        Serial.println("Card Mount Failed");
        return;
    }
}

void logToSD()
{
    if (!sdInitialised) return;
    if (!EMUfresh) return;

    if (!logStarted)
    {
        file = SD.open(filenameBuffer, FILE_APPEND);
        if (file)
        {
            file.print("Time,RPM,MAP,TPS,IAT,CLT,Lambda,PulseWidth,EGT1,EGT2,Vbatt,Baro,IgnAngle,LambdaCorr,Gear,Pwm1,Vss,EmuTemp,CEL,FLAGS1,LambdaTarget,OilTemp,OilPress,CanState\r\n");
            logStartTime = millis();
            logStarted = true;
        }
    }

    uint32_t duration = millis() - logStartTime;
    uint32_t seconds = duration / 1000;
    uint32_t milliseconds = duration % 1000;
    String dataString = "";

    dataString += seconds;
    dataString += ".";
    if (milliseconds < 100) { dataString += "0"; }
    if (milliseconds < 10) { dataString += "0"; }
    dataString += milliseconds;
    dataString += ",";
    dataString += String(emu_data.RPM);
    dataString += ",";
    dataString += String(emu_data.MAP);
    dataString += ",";
    dataString += String(emu_data.TPS);
    dataString += ",";
    dataString += String(emu_data.IAT);
    dataString += ",";
    dataString += String(emu_data.CLT);
    dataString += ",";
    dataString += String(emu_data.lambda);
    dataString += ",";
    dataString += String(emu_data.pulseWidth);
    dataString += ",";
    dataString += String(emu_data.EGT1);
    dataString += ",";
    dataString += String(emu_data.EGT2);
    dataString += ",";
    dataString += String(emu_data.vBat);
    dataString += ",";
    dataString += String(emu_data.baro);
    dataString += ",";
    dataString += String(emu_data.ignAngle, 0);
    dataString += ",";
    dataString += String(emu_data.lambdaCorr, 0);
    dataString += ",";
    dataString += String(emu_data.gear);
    dataString += ",";
    dataString += String(emu_data.pwm1);
    dataString += ",";
    dataString += String(emu_data.vssSpeed);
    dataString += ",";
    dataString += String(emu_data.emuTemp);
    dataString += ",";
    dataString += String(emu_data.cel);
    dataString += ",";
    dataString += String(emu_data.flags1);
    dataString += ",";
    dataString += String(emu_data.lambdaTarget);
    dataString += ",";
    dataString += String(emu_data.oilTemperature);
    dataString += ",";
    dataString += String(emu_data.oilPressure);
    //dataString += ",";
    //dataString += String(can_error_data.state[1]); //Only first character
    dataString += "\r\n";

    file.print(dataString.c_str());

    if (millis() - lastSyncTime > 1000)
    {
        lastSyncTime = millis();
        file.flush();
    }
}

void generateFileName()
{
    char intBuffer[5];

    strcpy(filenameBuffer, "/");
    itoa(random(1000, 9999), intBuffer, 10);
    strcat(filenameBuffer, intBuffer);
    strcat(filenameBuffer, "-");
    itoa(random(10), intBuffer, 10);
    strcat(filenameBuffer, intBuffer);
    strcat(filenameBuffer, "-");
    itoa(random(10), intBuffer, 10);
    strcat(filenameBuffer, intBuffer);
    strcat(filenameBuffer, "_");
    itoa(random(10), intBuffer, 10);
    strcat(filenameBuffer, intBuffer);
    strcat(filenameBuffer, ".");
    itoa(random(10), intBuffer, 10);
    strcat(filenameBuffer, intBuffer);
    strcat(filenameBuffer, ".");
    itoa(random(10), intBuffer, 10);
    strcat(filenameBuffer, intBuffer);
    strcat(filenameBuffer, ".csv");

    Serial.println(filenameBuffer);
}

Excess usage of String class is bad. Use a fixed char buffer instead

Can you also show the code that calls the function logToSD() at 20Hz ?
In the meantime,  maybe read this to see if it applies: https://www.best-microcontroller-projects.com/arduino-millis.html heading "Arduino millis not accurate".
In principle,  constructs like this (which you've used elsewhere)
if (millis() - lastSyncTime > 1000) { lastSyncTime = millis(); //...; } should be written as
if (millis() - lastSyncTime > 1000) { lastSyncTime +=1000; //...; } due to the way millis() derives 1000 milliseconds from 1024 timer ticks.

See also this thread for a discussion about the behaviour of millis() when timing regular events: https://forum.arduino.cc/t/millis-not-in-sync-with-8mhz-system-clock/179267


text:
Attiny timer interrupt does not make an interrupt every 1000ms
I'm making a stopwatch using an attiny85, the idea was to use the timer interrupts to count the seconds
my theory was: since I set the Attiny85 to run at 1Mhz, I can use a presale of 1024; 1000000 / 1024 = 976.5625 hz, 976.5625hz = 1.024ms, 125ms / 1.024ms = 122.07, so that I need to count to 122 to get a 125ms interrupt, then in the ISR function I can count to 8 to get around 1 second, ( 122 * 1.024 ) * 8 = 999.424ms
What is the problem? well, the problem is that I'm not getting something close to 999.424ms, I compere it with my phone's stopwatch and the attiny seems to start well, but then it gets about 2-3 slower than my phone's stopwatch
#include <TM1637Display.h>

#define CLK 4
#define DIO 3
#define button 1

TM1637Display display (CLK, DIO);
int intr_count = 0;
byte dots = 0b01000000;

volatile int seg;
volatile int min;
volatile bool start = false;

void setup() {
  display.setBrightness(5);
  display.clear();
  pinMode(button, INPUT);

  cli();

  TCCR0A  = 0;
  TCCR0B  = 0;
  TCCR0B |= B00000101;
  TIMSK  |= B00010000;

  OCR0A   = 122;

  sei();
}

void start_counting(){
  if (digitalRead(button) == HIGH){
    start = !start;
    if(start == false){
//    display.clear();
      seg = 0;
      min = 0;
    }
    while(digitalRead(button) == HIGH);
  }
}

void loop() {
  start_counting();
  display.showNumberDecEx(min, dots, true, 2, 0);
  display.showNumberDec(seg, true, 2, 2);

}

ISR(TIMER0_COMPA_vect) {
  TCNT0 = 0;
  if(start == true){

    if (intr_count == 8) {

      seg++;

      if(seg == 60){
        min++;
        min = min % 60;
      }

      seg = seg % 60;

      intr_count = 0;
    } else {
      intr_count++;
    }
  }
}

Are you running this from the internal oscillator? "2-3 slower" 2 to 3 what slower? Milliseconds? And this much slower over the course of what amount of real time?

@timemage yes I'm running the attiny from the internal oscillator . "2 - 3 " seconds  slower, time drift I should say , for example starting both stopwatches at the same time when my phone is 00:10 the attiny stopwatch is 00:08, when my phone is 1:00 the attiny stopwatch is 00:57, on the first seconds the stopwatches seem to be synchronized, but after couple of seconds my phone seems to "count the seconds" much faster

display.showNumberDec(seg, true, 2, 2); This, for example, is a non-atomic read operation on an int16_t. It could have been half updated by the ISR at the time of the call. Best is to suspend interrupts while making a copy of seg and display that.

" ( 122 * 1.024 ) * 8 = 999.424ms" . I guess then OCR0A should be 121 since it starts from 0.

@6v6gt Yeah. I noticed that also, but it's likely under the accuracy of the RC osc itself. It also makes sense to use a mode of the counter that automatically reset TCNT rather than doing that in software, but I don't know how important that will be ultimately either. I probably won't be looking at seriously again for another 10+ hours.

I uploaded the code on an Attiny45 using an external oscillator of 16Mhz, the time is also drifting, although less than with the internal 1Mhz of the Attiny85

It sounds like it is time for you to buy a RTC (Real Time Clock) module. That will be accurate.

You need to have an external 32.768kHz Low-Frequency Crystal Oscillator in order to produce accurate 1Hz clock and use it to configure the timer to generate a 1s clock that you need. Read the datasheet about Low-Frequency Crystal Oscillator and how to configure it.

If Edgar's answer doesn't just answer it, what sort of drift are you observing with the external 16Mhz and is it a crystal, resonator, etc?

I see three issues with this approach.
The first is that you are using a very low quality, uncalibrated time
source. The frequency of the internal RC oscillator is good to within a
few percent only. It is also very unstable, and hugely dependent on
temperature. Using an external 16 Mhz ceramic oscillator should
give you a frequency that is no worse than 0.5% off, with a typical
error about 0.1%. It is still somewhat unstable though. If you instead
are using a crystal oscillator, then you can expect an error about ten
times smaller (in the range of 100 ppm), and a very good stability.
Depending on you quality requirements, 100 ppm may still not be
good enough, in which case you still have the option to measure the
drift rate and calibrate it out (see below).
The second problem, which has already been raised by 6v6g, is that your
timer is counting from zero to 122 inclusive, which gives a period of
123 timer clock cycles. Take a look at the timing diagrams in the
datasheet if you need to convince yourself of this. If you want a period
of 122, you should set OCR0A to 121.
The third problem is that you are resetting the timer with the ISR. This
may work in this program, but it is a very fragile approach worth
avoiding. The problem is that everything the microcontroller does takes
time, and your ISR may even get delayed by another interrupt. If the
timer is incremented after rising the interrupt flag but before you
reset it, you are missing one count. If you want to have a continuous
time scale, never reset your timer. You can either:

let it run continuously, undisturbed (and do OCR0A += 122 within the
ISR),

or let it reset itself by using the appropriate waveform generation
mode (CTC or fast PWM).

Lastly, here is a trick you may use to calibrate your stop watch.
Instead of counting the interrupts until the counter reaches 8
(which assumes an interrupt period of exactly 1/8 s), increment a
nanosecond counter within the ISR, and count one second once you have
one billion nanoseconds:
const uint32_t nanoseconds_per_interrupt = 124928000;

ISR(TIMER0_COMPA_vect) {
    static uint32_t nanoseconds;
    nanoseconds += nanoseconds_per_interrupt;
    if (nanoseconds >= 1000000) {
        nanoseconds -= 1000000;
        seconds++;
        // then update minutes, hours... if needed
    }
}

This will increment the seconds every eight interrupts... most of the
time. From time to time, however, it will take nine interrupts. This
adds a little bit of jitter, but prevents the timing errors from
accumulating and making the clock drift. If the jitter is visible, you
can reduce it by shortening the interrupt period.
The value 124928000 I wrote above assumes the ISR is called every
122×1024 cycles of a 1 MHz clock. You can change it to fit a
different clock frequency or a different OCR0A setting. The trick is:
once you measure the drift rate of your stop watch, you can tweak this
number to remove that drift. For example, if you measure the stopwatch
and find it is running 0.04% too slow, then you increase that number by
0.04% (that would give 124977971) and the drift is gone.
Edit: In a comment, 6v6gt pointed out a fourth issue in your code,
which is likely the biggest issue. Your logic for counting interrupts
is:
if (intr_count == 8) {
    intr_count = 0;
} else {
    intr_count++;
}

This is counting from 0 to 8 inclusive, and looping with a period of
9 interrupts. A safer idiom for looping with a period of 8
would be:
if (++intr_count >= 8) {
    intr_count = 0;
}

Although I would still recommend counting nanoseconds if you want the
ability to calibrate your clock.

( 122 * 1.024 ) * 8 = 999.424ms Maybe the following from the OP is also wrong for the same reason the OCR0A was wrong:  if (intr_count == 8) { . .  It is call 7 (calls running from 0) of the ISR that indicates the end of a full second, not call 8

@6v6gt: Indeed you are right, and this looks like it should introduce a huge error. Added that to the answer.

Thank you, Edgar, for an extremely comprehensive answer. :)


text:
Having a problem with DS18B20 getTempC using an array containing the addresses of the sensors
I have been struggling with this and am at a total loss as to why its not working.
Here is my program:
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is Arduino pin A0
#define ONE_WIRE_BUS A0

// Setup a oneWire instance
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

// Define array for holding all the sensors addresses and load addresses.
//======================================================================
DeviceAddress SensorAddr [13] =
                 {
 ( 0x28, 0xAA, 0x30, 0x41, 0x38, 0x14, 0x01, 0x14 ), // Sensor 1
 ( 0x28, 0xAA, 0x24, 0x31, 0x38, 0x14, 0x01, 0xDF ), // Sensor 2
 ( 0x28, 0xAA, 0xE4, 0x30, 0x38, 0x14, 0x01, 0x72 ), // Sensor 3
 ( 0x28, 0xAA, 0xD4, 0xC2, 0x38, 0x14, 0x01, 0x80 ), // Sensor 4
 ( 0x28, 0xAA, 0x6C, 0xDA, 0x38, 0x14, 0x01, 0xD5 ), // Sensor 5
 ( 0x28, 0xAA, 0xCA, 0x39, 0x38, 0x14, 0x01, 0xBB ), // Sensor 6
 ( 0x28, 0xAA, 0x75, 0x28, 0x38, 0x14, 0x01, 0x2C ), // Sensor 7
 ( 0x28, 0xAA, 0xFB, 0xB2, 0x38, 0x14, 0x01, 0xBF ), // Sensor 8
 ( 0x28, 0xAA, 0x0F, 0x3A, 0x38, 0x14, 0x01, 0xC3 ), // Sensor 9
 ( 0x28, 0xAA, 0x6F, 0x26, 0x38, 0x14, 0x01, 0xF8 ), // Sensor 10
 ( 0x28, 0xFF, 0x64, 0x1E, 0x1E, 0x6A, 0x74, 0xF1 ), // Sensor 11
 ( 0x28, 0xFF, 0x64, 0x1E, 0x1E, 0x7D, 0x29, 0x55 ), // Sensor 12
 ( 0x28, 0xFF, 0x64, 0x1E, 0x1E, 0x73, 0xAC, 0x3A )  // Sensor 13
                   };

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

//Test first Sensor Address  - This works
//=======================================

  byte Sensor1Test[8] = { 0x28, 0xAA, 0x30, 0x41, 0x38, 0x14, 0x01, 0x14};
  Serial.print("Test Sensor 1: ");
  float tempTest = sensors.getTempC( Sensor1Test );
  Serial.print(tempTest, 2);
  Serial.print("\xC2\xB0"); // shows degree symbol
  Serial.print("C");
  Serial.println();
}

void loop(void)
// Get all temperatures - This does not work??
//============================================

{
  sensors.requestTemperatures();
  for (int S =0; S<13; S++)
      {
        Serial.print("Sensor # "); Serial.print(S+1); Serial.print(": ");
        float tempC = sensors.getTempC(SensorAddr [S]);
        Serial.print(tempC,2);
        Serial.print("\xC2\xB0"); // shows degree symbol
        Serial.print("C");
        Serial.println();
        delay(1000);
      }
 Serial.println();
}

please, no pictures of text ... delete the picture and add the text

Go through the tutorial at https://lastminuteengineers.com/multiple-ds18b20-arduino-tutorial. Try using their code for reading multiple sensors by address (or index, but you are trying to read by address).  Try doing the read loop the way they are doing it and using uint8_t arrays - it can't hurt. Let us know how that goes please.

that is not how this site works ... please post the updated code in an answer and explain how the problem was solved ... rolled back your edit

The DeviceAddress internally is defined as an array of uint8_t (see definition:
typedef uint8_t DeviceAddress[8];

That is, each address is an array itself.
DeviceAddress Sensor1 = { 0x28, 0xAA, 0x30, 0x41, 0x38, 0x14, 0x01, 0x14 };

So if you have 13 DeviceAdrress, you are dealing with a two-dimension array, and you need to declare it as:
#define NUMBER_OF_SENSORS 13
DeviceAddress SensorAddr [NUMBER_OF_SENSORS] = {
 { 0x28, 0xAA, 0x30, 0x41, 0x38, 0x14, 0x01, 0x14 }, // Sensor 1
 { 0x28, 0xAA, 0x24, 0x31, 0x38, 0x14, 0x01, 0xDF }, // Sensor 2
 { 0x28, 0xAA, 0xE4, 0x30, 0x38, 0x14, 0x01, 0x72 }, // Sensor 3
 { 0x28, 0xAA, 0xD4, 0xC2, 0x38, 0x14, 0x01, 0x80 }, // Sensor 4
 { 0x28, 0xAA, 0x6C, 0xDA, 0x38, 0x14, 0x01, 0xD5 }, // Sensor 5
 { 0x28, 0xAA, 0xCA, 0x39, 0x38, 0x14, 0x01, 0xBB }, // Sensor 6
 { 0x28, 0xAA, 0x75, 0x28, 0x38, 0x14, 0x01, 0x2C }, // Sensor 7
 { 0x28, 0xAA, 0xFB, 0xB2, 0x38, 0x14, 0x01, 0xBF }, // Sensor 8
 { 0x28, 0xAA, 0x0F, 0x3A, 0x38, 0x14, 0x01, 0xC3 }, // Sensor 9
 { 0x28, 0xAA, 0x6F, 0x26, 0x38, 0x14, 0x01, 0xF8 }, // Sensor 10
 { 0x28, 0xFF, 0x64, 0x1E, 0x1E, 0x6A, 0x74, 0xF1 }, // Sensor 11
 { 0x28, 0xFF, 0x64, 0x1E, 0x1E, 0x7D, 0x29, 0x55 }, // Sensor 12
 { 0x28, 0xFF, 0x64, 0x1E, 0x1E, 0x73, 0xAC, 0x3A }  // Sensor 13
};

for (int s=0; s<NUMBER_OF_SENSORS; S++) {
  float tempC = sensors.getTempC(SensorAddr[s]);
}


text:
Arduino Sleep to conserve battery - How to intergrade it to existing sketch - HELP pls
My sketch below is simply using a touch sensor to activate a servo motor to go from from initial position 0 to 180 then back to 0. then I want the Adruino NANO to go to sleep to conserve some battery life.
Being a novice to programing and after many attempts to use his code and intergrade it with mine. Was unsuccessful.
so if anyone can help intergrade the gammon's sketch below into mine it would be greatly appreciated. As I'm out of ideas.
HERE IS MY SKETCH
#include <Servo.h>

// constants won't change
const int SENSOR = 2; // Arduino pin connected to motion sensor's pin 7
const int SERVO = 9; // Arduino pin connected to servo motor's pin 9

Servo servo; // create servo object to control a servo

int pos = 0; // variable to store the servo position

// variables will change:
int lastMotionState; // the previous state of motion sensor
int currentMotionState; // the current state of motion sensor

void setup() {

Serial.begin(9600); // initialize serial
pinMode(SENSOR, INPUT); // set arduino pin 9 to input mode
servo.attach(SERVO); // attaches the servo on pin 12 to the servo object

servo.write(0);
currentMotionState = digitalRead(SENSOR);
}

void loop() {
lastMotionState = currentMotionState; // save the last state
currentMotionState = digitalRead(SENSOR); // read new state

if (currentMotionState == LOW && lastMotionState == HIGH) { // pin state change: LOW -> HIGH
Serial.println("OFF");
servo.write(0);
delay(100); // waits (X)ms for the servo to reach the position
}
else
if (currentMotionState == HIGH && lastMotionState == LOW) { // pin state change: HIGH -> LOW
Serial.println("ACTIVE");
servo.write(180);
delay(2000); // waits (x)ms for the servo to reach the position
}
delay(10); // repeats program - larger delay - trigger is
}

______________________________________
Author:Ab Kurk  SLEEP SKETCH
This sketch is part of the beginners guide to putting your Arduino to sleep
tutorial. It is to demonstrate how to put your arduino into deep sleep and
how to wake it up.
*/
#include <avr/sleep.h>//this AVR library contains the methods that controls the sleep modes
#define interruptPin 2 //Pin we are going to use to wake up the Arduino

void setup() {
Serial.begin(115200);//Start Serial Comunication
pinMode(LED_BUILTIN,OUTPUT);//We use the led on pin 13 to indecate when Arduino is A sleep
pinMode(interruptPin,INPUT_PULLUP);//Set pin d2 to input using the buildin pullup resistor
digitalWrite(LED_BUILTIN,HIGH);//turning LED on
}

void loop() {
delay(5000);//wait 5 seconds before going to sleep
Going_To_Sleep();
}

void Going_To_Sleep(){
sleep_enable();//Enabling sleep mode
attachInterrupt(0, wakeUp, LOW);//attaching a interrupt to pin d2
set_sleep_mode(SLEEP_MODE_PWR_DOWN);//Setting the sleep mode, in our case full sleep
digitalWrite(LED_BUILTIN,LOW);//turning LED off
delay(1000); //wait a second to allow the led to be turned off before going to sleep
sleep_cpu();//activating sleep mode
Serial.println("just woke up!");//next line of code executed after the interrupt
digitalWrite(LED_BUILTIN,HIGH);//turning LED on
}

void wakeUp(){
Serial.println("Interrrupt Fired");//Print message to serial monitor
sleep_disable();//Disable sleep mode

detachInterrupt(0); //Removes the interrupt from pin 2;

}

please ask a question ... this is a Q&A site

Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer.

Question was how to incorporate my my sketch with an Kirk’s.

I'm going to guess that you are doing something like a door or safe lock, which may occasionally be used to activate a motor to unlock something but 99.99% of the time is sitting there doing nothing, and you want to save power in that time.
You need to rework somewhat.

An interrupt to detect a switch press. Then the processor can sleep, using very little power.

The interrupt, when it happens, wakes the processor

You activate the motor to unlock the door or whatever-it-is.

You put the processor into low power mode, and go back to sleep

Since my name was mentioned in the question, tips for doing low-power stuff are at this link. And here for stuff about interrupts.
Plus a slightly abridged version (due to space limitations) here on this site.
(You aren't supposed to make answers where the answer is totally in the link, but in this case the link is just supplementary material)

"You aren't supposed to make answers where the answer is totally in the link...".  I totally understand Nick.  Power management is complex, really depends on the HW (i.e. processor & circuit you are using) and should not be "added" to a project.  Rather the project (including the HW) should be built around power management.

Your right about my project.
Thank you for the info will go though it this weekend and attempt to get this thing to work


text:
Compilation Error
Hi everyone I seem to have run into a problem while uploading a library to the board. I managed to import the library to Arduino Uno, however, i could not upload it
Please Help :)
Thanks in Advance
This is the error i received:
Arduino: 1.6.11 Hourly Build 2016/08/05 02:12 (Mac OS X), Board: "Arduino/Genuino Uno"

In file included from /Users/pendukenipandeni/Documents/Arduino/SimpleTimer/SimpleTimer.ino:1:0:
/Users/pendukenipandeni/Documents/Arduino/libraries/SimpleTimer-master/SimpleTimer.h:37:22: fatal error: functional: No such file or directory
 #include <functional>
                      ^
compilation terminated.
exit status 1
Error compiling for board Arduino/Genuino Uno.

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

Where did you get that library?

I got the library from gitHub : https://github.com/schinken/SimpleTimer

Looks like that uses std::function which is not in the normal Arduino compiler (by the looks of things) - or not in the version I have anyway. Maybe you need a specific installation for it to work. Simplest option is to pick one of the many other implementations of SimpleTimer out there.

Thank you Majenko, i picked another Simple Timer and it works now

please help, #include <IRremote.h> ^ compilation terminated. exit status 1 Error compiling for board Arduino/Genuino Uno.

I managed to fix this by simply downloading and uploading a different SimpleTimer Library from https://github.com/jfturcot/SimpleTimer

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


text:
EB - 4x4 Soft Keypad Driver Diagram from Makerstudio needed
I have found this interesting device wile looking for a cheap Arduino.

It's a "driver" that converts a 4x4 Keyboard 8-PIN (8-IO)
to a 4-Pin (2-IO) Device
I would like to know if is Achieved by a shift register ,One Wire Keypad or some other magic. If you have a diagram/tutorial/video please share (I know the "One Wire Keypad" uses Only 3-PINS (1-Analog-IO))Naturally ordered one to have a look but its gonna take some time to get here and i am way to exited.

If you can identify the chip that's on it that should give you all the information you need.  Chances are it's an I2C interface.

The chip is a tm1650. But I don't know how it is being used on makerstudio.cc their is a lib to use it.But i have not had time to use it yet .

Have you thought to ask Google then?  5 seconds, and I have Arduino library: http://playground.arduino.cc/Main/TM1650 and datasheet: http://www.datasheetspdf.com/datasheet/download.php?id=840047 which though in Chinese has certain words like "SDA" and "SCL" in English. Like I guessed, it's an I2C interface.

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


text:
240*320 transparent OLED display with Arduino
A long time ago I ordered this transparent OLED display (from a chinese supplier on alibaba) planning on interfacing it with an Arduino but didn't really have the skills to get the project going.
I have the datasheet (linked below) for the driver and it seems to come with a schematic on it which takes the output from the OLED and gives me 8-bit wiring. My plan is to use the adafruit GFX library with it and probably steal the code from this adafruit TFT.
Please, someone tell me if this has no hope of working but my plan as it stands is:
1) draw up the datasheets schematic into Kicad, and get it printed onto a PCB (I am worried that if I breadboard/protoboard it, ill have all kinds of issues coming from my poor perfboarding skills and I want to be able to narrow down my problems. I know it's bad practise to print a PCB before doing any breadboarding but I don't think ill successfully manage it)
2) wire up the output pins from the new PCB in the same way that the adafruit board and try and use the same code.
3) Here are where the problems come I think as I am proficient at simple code (I'm probably being ignorant to the fact that 'simple' code is still way above my level) e.g functions/loops etc... but writing code like adafruits example for displays is way above my level. I hope that I can just edit some of Adafruits existing example code and it will just work.
A few years ago I asked a similar question on the Arduino forum but then I was much worse at programming and had less of an idea where to start.
If any of you can provide insight into if this will work or any better ideas then I am all ears.
Thanks
Documents containing datasheets and example code - https://drive.google.com/drive/folders/1ZTmipJKRKWNMudYVQ5ATxixbQtKD4hQm?usp=sharing

edit:
there is also a file called example_code.txt which contains a lot of (I dont know what I'm talking about really) hex commands.
edit 2: - ILI9341 Mock Example
/***************************************************
  This is our GFX example for the Adafruit ILI9341 Breakout and Shield
  ----> http://www.adafruit.com/products/1651

  Check out the links above for our tutorials and wiring diagrams
  These displays use SPI to communicate, 4 or 5 pins are required to
  interface (RST is optional)
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  MIT license, all text above must be included in any redistribution
 ****************************************************/

#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"

// For the Adafruit shield, these are the default.
#define TFT_DC 9
#define TFT_CS 10

// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
// If using the breakout, change pins as desired
//Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);

void setup() {
  Serial.begin(9600);
  Serial.println("ILI9341 Test!");

  tft.begin();

  // read diagnostics (optional but can help debug problems)
  uint8_t x = tft.readcommand8(ILI9341_RDMODE);
  Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDMADCTL);
  Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDPIXFMT);
  Serial.print("Pixel Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDIMGFMT);
  Serial.print("Image Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDSELFDIAG);
  Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX);

  Serial.println(F("Benchmark                Time (microseconds)"));
  delay(10);
  Serial.print(F("Screen fill              "));
  Serial.println(testFillScreen());
  delay(500);

  Serial.print(F("Text                     "));
  Serial.println(testText());
  delay(3000);

  Serial.print(F("Lines                    "));
  Serial.println(testLines(ILI9341_CYAN));
  delay(500);

  Serial.print(F("Horiz/Vert Lines         "));
  Serial.println(testFastLines(ILI9341_RED, ILI9341_BLUE));
  delay(500);

  Serial.print(F("Rectangles (outline)     "));
  Serial.println(testRects(ILI9341_GREEN));
  delay(500);

  Serial.print(F("Rectangles (filled)      "));
  Serial.println(testFilledRects(ILI9341_YELLOW, ILI9341_MAGENTA));
  delay(500);

  Serial.print(F("Circles (filled)         "));
  Serial.println(testFilledCircles(10, ILI9341_MAGENTA));

  Serial.print(F("Circles (outline)        "));
  Serial.println(testCircles(10, ILI9341_WHITE));
  delay(500);

  Serial.print(F("Triangles (outline)      "));
  Serial.println(testTriangles());
  delay(500);

  Serial.print(F("Triangles (filled)       "));
  Serial.println(testFilledTriangles());
  delay(500);

  Serial.print(F("Rounded rects (outline)  "));
  Serial.println(testRoundRects());
  delay(500);

  Serial.print(F("Rounded rects (filled)   "));
  Serial.println(testFilledRoundRects());
  delay(500);

  Serial.println(F("Done!"));

}

void loop(void) {
  for(uint8_t rotation=0; rotation<4; rotation++) {
    tft.setRotation(rotation);
    testText();
    delay(1000);
  }
}

unsigned long testFillScreen() {
  unsigned long start = micros();
  tft.fillScreen(ILI9341_BLACK);
  yield();
  tft.fillScreen(ILI9341_RED);
  yield();
  tft.fillScreen(ILI9341_GREEN);
  yield();
  tft.fillScreen(ILI9341_BLUE);
  yield();
  tft.fillScreen(ILI9341_BLACK);
  yield();
  return micros() - start;
}

unsigned long testText() {
  tft.fillScreen(ILI9341_BLACK);
  unsigned long start = micros();
  tft.setCursor(0, 0);
  tft.setTextColor(ILI9341_WHITE);  tft.setTextSize(1);
  tft.println("Hello World!");
  tft.setTextColor(ILI9341_YELLOW); tft.setTextSize(2);
  tft.println(1234.56);
  tft.setTextColor(ILI9341_RED);    tft.setTextSize(3);
  tft.println(0xDEADBEEF, HEX);
  tft.println();
  tft.setTextColor(ILI9341_GREEN);
  tft.setTextSize(5);
  tft.println("Groop");
  tft.setTextSize(2);
  tft.println("I implore thee,");
  tft.setTextSize(1);
  tft.println("my foonting turlingdromes.");
  tft.println("And hooptiously drangle me");
  tft.println("with crinkly bindlewurdles,");
  tft.println("Or I will rend thee");
  tft.println("in the gobberwarts");
  tft.println("with my blurglecruncheon,");
  tft.println("see if I don't!");
  return micros() - start;
}

unsigned long testLines(uint16_t color) {
  unsigned long start, t;
  int           x1, y1, x2, y2,
                w = tft.width(),
                h = tft.height();

  tft.fillScreen(ILI9341_BLACK);
  yield();

  x1 = y1 = 0;
  y2    = h - 1;
  start = micros();
  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = w - 1;
  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
  t     = micros() - start; // fillScreen doesn't count against timing

  yield();
  tft.fillScreen(ILI9341_BLACK);
  yield();

  x1    = w - 1;
  y1    = 0;
  y2    = h - 1;
  start = micros();
  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = 0;
  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
  t    += micros() - start;

  yield();
  tft.fillScreen(ILI9341_BLACK);
  yield();

  x1    = 0;
  y1    = h - 1;
  y2    = 0;
  start = micros();
  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = w - 1;
  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
  t    += micros() - start;

  yield();
  tft.fillScreen(ILI9341_BLACK);
  yield();

  x1    = w - 1;
  y1    = h - 1;
  y2    = 0;
  start = micros();
  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = 0;
  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);

  yield();
  return micros() - start;
}

unsigned long testFastLines(uint16_t color1, uint16_t color2) {
  unsigned long start;
  int           x, y, w = tft.width(), h = tft.height();

  tft.fillScreen(ILI9341_BLACK);
  start = micros();
  for(y=0; y<h; y+=5) tft.drawFastHLine(0, y, w, color1);
  for(x=0; x<w; x+=5) tft.drawFastVLine(x, 0, h, color2);

  return micros() - start;
}

unsigned long testRects(uint16_t color) {
  unsigned long start;
  int           n, i, i2,
                cx = tft.width()  / 2,
                cy = tft.height() / 2;

  tft.fillScreen(ILI9341_BLACK);
  n     = min(tft.width(), tft.height());
  start = micros();
  for(i=2; i<n; i+=6) {
    i2 = i / 2;
    tft.drawRect(cx-i2, cy-i2, i, i, color);
  }

  return micros() - start;
}

unsigned long testFilledRects(uint16_t color1, uint16_t color2) {
  unsigned long start, t = 0;
  int           n, i, i2,
                cx = tft.width()  / 2 - 1,
                cy = tft.height() / 2 - 1;

  tft.fillScreen(ILI9341_BLACK);
  n = min(tft.width(), tft.height());
  for(i=n; i>0; i-=6) {
    i2    = i / 2;
    start = micros();
    tft.fillRect(cx-i2, cy-i2, i, i, color1);
    t    += micros() - start;
    // Outlines are not included in timing results
    tft.drawRect(cx-i2, cy-i2, i, i, color2);
    yield();
  }

  return t;
}

unsigned long testFilledCircles(uint8_t radius, uint16_t color) {
  unsigned long start;
  int x, y, w = tft.width(), h = tft.height(), r2 = radius * 2;

  tft.fillScreen(ILI9341_BLACK);
  start = micros();
  for(x=radius; x<w; x+=r2) {
    for(y=radius; y<h; y+=r2) {
      tft.fillCircle(x, y, radius, color);
    }
  }

  return micros() - start;
}

unsigned long testCircles(uint8_t radius, uint16_t color) {
  unsigned long start;
  int           x, y, r2 = radius * 2,
                w = tft.width()  + radius,
                h = tft.height() + radius;

  // Screen is not cleared for this one -- this is
  // intentional and does not affect the reported time.
  start = micros();
  for(x=0; x<w; x+=r2) {
    for(y=0; y<h; y+=r2) {
      tft.drawCircle(x, y, radius, color);
    }
  }

  return micros() - start;
}

unsigned long testTriangles() {
  unsigned long start;
  int           n, i, cx = tft.width()  / 2 - 1,
                      cy = tft.height() / 2 - 1;

  tft.fillScreen(ILI9341_BLACK);
  n     = min(cx, cy);
  start = micros();
  for(i=0; i<n; i+=5) {
    tft.drawTriangle(
      cx    , cy - i, // peak
      cx - i, cy + i, // bottom left
      cx + i, cy + i, // bottom right
      tft.color565(i, i, i));
  }

  return micros() - start;
}

unsigned long testFilledTriangles() {
  unsigned long start, t = 0;
  int           i, cx = tft.width()  / 2 - 1,
                   cy = tft.height() / 2 - 1;

  tft.fillScreen(ILI9341_BLACK);
  start = micros();
  for(i=min(cx,cy); i>10; i-=5) {
    start = micros();
    tft.fillTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
      tft.color565(0, i*10, i*10));
    t += micros() - start;
    tft.drawTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
      tft.color565(i*10, i*10, 0));
    yield();
  }

  return t;
}

unsigned long testRoundRects() {
  unsigned long start;
  int           w, i, i2,
                cx = tft.width()  / 2 - 1,
                cy = tft.height() / 2 - 1;

  tft.fillScreen(ILI9341_BLACK);
  w     = min(tft.width(), tft.height());
  start = micros();
  for(i=0; i<w; i+=6) {
    i2 = i / 2;
    tft.drawRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(i, 0, 0));
  }

  return micros() - start;
}

unsigned long testFilledRoundRects() {
  unsigned long start;
  int           i, i2,
                cx = tft.width()  / 2 - 1,
                cy = tft.height() / 2 - 1;

  tft.fillScreen(ILI9341_BLACK);
  start = micros();
  for(i=min(tft.width(), tft.height()); i>20; i-=6) {
    i2 = i / 2;
    tft.fillRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(0, i, 0));
    yield();
  }

  return micros() - start;
}

edit 3: - ili9341 header file
/*!
 * @file Adafruit_ILI9341.h
 *
 * This is the documentation for Adafruit's ILI9341 driver for the
 * Arduino platform.
 *
 * This library works with the Adafruit 2.8" Touch Shield V2 (SPI)
 *    http://www.adafruit.com/products/1651
 * Adafruit 2.4" TFT LCD with Touchscreen Breakout w/MicroSD Socket - ILI9341
 *    https://www.adafruit.com/product/2478
 * 2.8" TFT LCD with Touchscreen Breakout Board w/MicroSD Socket - ILI9341
 *    https://www.adafruit.com/product/1770
 * 2.2" 18-bit color TFT LCD display with microSD card breakout - ILI9340
 *    https://www.adafruit.com/product/1770
 * TFT FeatherWing - 2.4" 320x240 Touchscreen For All Feathers
 *    https://www.adafruit.com/product/3315
 *
 * These displays use SPI to communicate, 4 or 5 pins are required
 * to interface (RST is optional).
 *
 * Adafruit invests time and resources providing this open source code,
 * please support Adafruit and open-source hardware by purchasing
 * products from Adafruit!
 *
 *
 * This library depends on
 * Adafruit_GFX being present on your system. Please make sure you have
 * installed the latest version before using this library.
 *
 * Written by Limor "ladyada" Fried for Adafruit Industries.
 *
 * BSD license, all text here must be included in any redistribution.
 *
 */

#ifndef _ADAFRUIT_ILI9341H_
#define _ADAFRUIT_ILI9341H_

#include "Adafruit_GFX.h"
#include "Arduino.h"
#include "Print.h"
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <SPI.h>

#define ILI9341_TFTWIDTH 240  ///< ILI9341 max TFT width
#define ILI9341_TFTHEIGHT 320 ///< ILI9341 max TFT height

#define ILI9341_NOP 0x00     ///< No-op register
#define ILI9341_SWRESET 0x01 ///< Software reset register
#define ILI9341_RDDID 0x04   ///< Read display identification information
#define ILI9341_RDDST 0x09   ///< Read Display Status

#define ILI9341_SLPIN 0x10  ///< Enter Sleep Mode
#define ILI9341_SLPOUT 0x11 ///< Sleep Out
#define ILI9341_PTLON 0x12  ///< Partial Mode ON
#define ILI9341_NORON 0x13  ///< Normal Display Mode ON

#define ILI9341_RDMODE 0x0A     ///< Read Display Power Mode
#define ILI9341_RDMADCTL 0x0B   ///< Read Display MADCTL
#define ILI9341_RDPIXFMT 0x0C   ///< Read Display Pixel Format
#define ILI9341_RDIMGFMT 0x0D   ///< Read Display Image Format
#define ILI9341_RDSELFDIAG 0x0F ///< Read Display Self-Diagnostic Result

#define ILI9341_INVOFF 0x20   ///< Display Inversion OFF
#define ILI9341_INVON 0x21    ///< Display Inversion ON
#define ILI9341_GAMMASET 0x26 ///< Gamma Set
#define ILI9341_DISPOFF 0x28  ///< Display OFF
#define ILI9341_DISPON 0x29   ///< Display ON

#define ILI9341_CASET 0x2A ///< Column Address Set
#define ILI9341_PASET 0x2B ///< Page Address Set
#define ILI9341_RAMWR 0x2C ///< Memory Write
#define ILI9341_RAMRD 0x2E ///< Memory Read

#define ILI9341_PTLAR 0x30    ///< Partial Area
#define ILI9341_VSCRDEF 0x33  ///< Vertical Scrolling Definition
#define ILI9341_MADCTL 0x36   ///< Memory Access Control
#define ILI9341_VSCRSADD 0x37 ///< Vertical Scrolling Start Address
#define ILI9341_PIXFMT 0x3A   ///< COLMOD: Pixel Format Set

#define ILI9341_FRMCTR1                                                        \
  0xB1 ///< Frame Rate Control (In Normal Mode/Full Colors)
#define ILI9341_FRMCTR2 0xB2 ///< Frame Rate Control (In Idle Mode/8 colors)
#define ILI9341_FRMCTR3                                                        \
  0xB3 ///< Frame Rate control (In Partial Mode/Full Colors)
#define ILI9341_INVCTR 0xB4  ///< Display Inversion Control
#define ILI9341_DFUNCTR 0xB6 ///< Display Function Control

#define ILI9341_PWCTR1 0xC0 ///< Power Control 1
#define ILI9341_PWCTR2 0xC1 ///< Power Control 2
#define ILI9341_PWCTR3 0xC2 ///< Power Control 3
#define ILI9341_PWCTR4 0xC3 ///< Power Control 4
#define ILI9341_PWCTR5 0xC4 ///< Power Control 5
#define ILI9341_VMCTR1 0xC5 ///< VCOM Control 1
#define ILI9341_VMCTR2 0xC7 ///< VCOM Control 2

#define ILI9341_RDID1 0xDA ///< Read ID 1
#define ILI9341_RDID2 0xDB ///< Read ID 2
#define ILI9341_RDID3 0xDC ///< Read ID 3
#define ILI9341_RDID4 0xDD ///< Read ID 4

#define ILI9341_GMCTRP1 0xE0 ///< Positive Gamma Correction
#define ILI9341_GMCTRN1 0xE1 ///< Negative Gamma Correction
//#define ILI9341_PWCTR6     0xFC

// Color definitions
#define ILI9341_BLACK 0x0000       ///<   0,   0,   0
#define ILI9341_NAVY 0x000F        ///<   0,   0, 123
#define ILI9341_DARKGREEN 0x03E0   ///<   0, 125,   0
#define ILI9341_DARKCYAN 0x03EF    ///<   0, 125, 123
#define ILI9341_MAROON 0x7800      ///< 123,   0,   0
#define ILI9341_PURPLE 0x780F      ///< 123,   0, 123
#define ILI9341_OLIVE 0x7BE0       ///< 123, 125,   0
#define ILI9341_LIGHTGREY 0xC618   ///< 198, 195, 198
#define ILI9341_DARKGREY 0x7BEF    ///< 123, 125, 123
#define ILI9341_BLUE 0x001F        ///<   0,   0, 255
#define ILI9341_GREEN 0x07E0       ///<   0, 255,   0
#define ILI9341_CYAN 0x07FF        ///<   0, 255, 255
#define ILI9341_RED 0xF800         ///< 255,   0,   0
#define ILI9341_MAGENTA 0xF81F     ///< 255,   0, 255
#define ILI9341_YELLOW 0xFFE0      ///< 255, 255,   0
#define ILI9341_WHITE 0xFFFF       ///< 255, 255, 255
#define ILI9341_ORANGE 0xFD20      ///< 255, 165,   0
#define ILI9341_GREENYELLOW 0xAFE5 ///< 173, 255,  41
#define ILI9341_PINK 0xFC18        ///< 255, 130, 198

/**************************************************************************/
/*!
@brief Class to manage hardware interface with ILI9341 chipset (also seems to
work with ILI9340)
*/
/**************************************************************************/

class Adafruit_ILI9341 : public Adafruit_SPITFT {
public:
  Adafruit_ILI9341(int8_t _CS, int8_t _DC, int8_t _MOSI, int8_t _SCLK,
                   int8_t _RST = -1, int8_t _MISO = -1);
  Adafruit_ILI9341(int8_t _CS, int8_t _DC, int8_t _RST = -1);
#if !defined(ESP8266)
  Adafruit_ILI9341(SPIClass *spiClass, int8_t dc, int8_t cs = -1,
                   int8_t rst = -1);
#endif // end !ESP8266
  Adafruit_ILI9341(tftBusWidth busWidth, int8_t d0, int8_t wr, int8_t dc,
                   int8_t cs = -1, int8_t rst = -1, int8_t rd = -1);

  void begin(uint32_t freq = 0);
  void setRotation(uint8_t r);
  void invertDisplay(bool i);
  void scrollTo(uint16_t y);
  void setScrollMargins(uint16_t top, uint16_t bottom);

  // Transaction API not used by GFX
  void setAddrWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h);

  uint8_t readcommand8(uint8_t reg, uint8_t index = 0);
};

#endif // _ADAFRUIT_ILI9341H_

Anyone know of any similar/replacement screen for this model, TP241MC01G? It is discontinued. Having a tough time finding any transparent oled larger than 1.5" (128x64).

The critical part, assuming your hardware works, is getting the software going. Not all OLEDs are the same, and different ones need different commands to get them working.
You can't just take a random OLED and use a random library - it needs a driver to make it work.
In this case it's the DA8620 that is the main chip that you want to worry about, and your chosen library has to implement the commands and methodologies for that specific chip.
Now, you have a file that contains those commands (all the "hex commands"), and if you can't find an existing library to work with the DA8620 then you will have to write or adapt one while referring to those commands.  You can find out more about what the commands all mean by referencing the datasheet, which lists all the commands and their parameters (from page 78 onwards), so you should be able to relate those to what an existing library needs and map things accordingly while keeping the right power-up sequences.

Thanks for the info. Unfortunately, the DA8620 seems to be niche and also discontinued so it's very tricky to find any information let alone an Arduino driver. If I decided to try and adapt an existing library, for example, the Adafruit GFX, would it be so easy as changing some commands in the library to match the commands written in the datasheet? I assume that is not how it works at all and I am probably way out of my depth here.
How would I go about changing a library? Thanks

@VosemMedia That is probably exactly how it works. Find what the library does, and then find the commands that do that job in the datasheet and match those to the examples in the file of commands you have.

Okay, thankyou. Do you have any reccomendations for libraries to start with? Do you think that one I linked earlier would be an okay starting point? Thanks

The Adafruit one is good because it is split into sections - one for the drawing primitives (the GFX library) and the other for the OLED driver.

Okay, I edited in an adafruit GFX example code for some irrelivent 2.4" tft. It references some functions like tft.setTextColor and tft.println. I need to edit those functions right? Or am I on the completely wrong line and should be looking somewhere else. If im not, would these magical commands be in Adafruit_GFX.h or Adafruit_ILI9341.h? Thanks

Adafruit_GFX,h is the parent class. It contains the high level stuff that you as a user interact with.  It neither knows nor cares what the OLED is.  Adafruit_ILI9341.h is the low level OLED / LCD interaction code and is what you should be editing.

Wow, this looks really promising. I edited in the Adafruit_ILI9341.h as well. The language on the datasheet is very similar to the language on the header file which looks good. Providing the hardware works and I manage to edit in all the commands correctly, should I be able to run the ILI9341 example .ino file and it all work smoothly? Cheers again for the help

That is what is to be hoped for, yes.

There is a 0x06 (RDRED Read Red Color) 0x07 (green) 0x08 (blue) in the datasheet but not in the header. Should I add it in?

There are also a number of ones that only exist in the header file (0x10, 0x11,0x12, 0x13)

The header should contain what you need. Remove anything that is specific to the old LCD and replace it with equivalents from the new OLED. If there are things about the OLED that the library doesn't want then just ignore them. If there are things that the old library does that aren't immediately obvious how to do in the new OLED then you have to get creative.  Any #defines are purely symbolic for your own programming use. If you want them then have them. If you don't want them then don't have them.

Your initial code.txt file is flawed.
The pdf file has the code in multiple columns on each page, and not all the columns are filled.
This is the code (i think it is correct)

Example of Initial Code

Command(0x11);
Data(0x00);

Delay_ms(255);   // Delay 255ms or more

Command(0xC5);
Data(0x01);

Command(0xC4);
Data(0x2F);

Command(0xC0);
Data(0x10);
Data(0x00);

Command(0x26);
Data(0x00);

Command(0x2A);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0xEF);

Command(0x2B);
Data(0x00);
Data(0x00);
Data(0x01);
Data(0x3F);

Command(0x36);
Data(0x08);

Command(0xC0);
Data(0x50);
Data(0x00);

Command(0x3A);
Data(0x65);    //Pixel Format 16bit data
//Data(0x67);  //Pixel Format 24bit data

Command(0xBB);
Data(0x4D);
Data(0x97);
Data(0x1C);

Command(0xC1);
Data(0x01);

Command(0xC6);
Data(0x6B);
Data(0x02);
Data(0x00);
Data(0x06);
Data(0x06);
Data(0x06);

Command(0xC9);
Data(0xF0);

Command(0xE0);
Data(0xC0);
Data(0x00);

Command(0xE2);
Data(0x00);

Command(0xE8);
Data(0x23);
Data(0x00);
Data(0x00);

Command(0xEB);
Data(0xC0);

Command(0xD9);
Data(0x40);
Data(0x00);

Command(0xD1);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);

Command(0xDF);
Data(0x35);
Data(0xAD);
Data(0x1C);
Data(0xE7);
Data(0x18);
Data(0xC6);
Data(0x14);
Data(0xA5);
Data(0x18);
Data(0xC6);
Data(0x14);
Data(0xA5);
Data(0x18);
Data(0xC6);
Data(0x14);
Data(0xA5);
Data(0x18);
Data(0xC6);
Data(0x14);
Data(0xA5);
Data(0x18);
Data(0xC6);
Data(0x14);
Data(0xA5);
Data(0x14);
Data(0xA5);
Data(0x18);
Data(0xC6);
Data(0x14);
Data(0xA5);
Data(0x18);
Data(0xC6);
Data(0x14);
Data(0xA5);
Data(0x18);
Data(0xC6);
Data(0x10);
Data(0x84);
Data(0x1C);
Data(0xE7);
Data(0x14);
Data(0xA5);
Data(0x10);
Data(0x84);
Data(0x1C);
Data(0xE7);
Data(0x08);
Data(0x42);
Data(0x0C);
Data(0x63);
Data(0x08);
Data(0x42);
Data(0x0C);
Data(0x63);
Data(0x10);
Data(0x84);
Data(0x08);
Data(0x42);
Data(0x0C);
Data(0x63);
Data(0x08);
Data(0x42);
Data(0x0C);
Data(0x63);
Data(0x10);
Data(0x84);
Data(0x14);
Data(0xA5);
Data(0x08);
Data(0x42);
Data(0x08);
Data(0x42);
Data(0x14);
Data(0xA5);
Data(0x0C);
Data(0x63);
Data(0x08);
Data(0x42);
Data(0x14);
Data(0xA5);
Data(0x08);
Data(0x42);
Data(0x08);
Data(0x42);
Data(0x0C);
Data(0x63);
Data(0x08);
Data(0x42);
Data(0x14);
Data(0xA5);
Data(0x14);
Data(0xA5);
Data(0x08);
Data(0x42);
Data(0x0C);
Data(0x63);

Command(0xD0);
Data(0x9F);
Data(0x19);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x00);
Data(0x0D);
Data(0xFF);
Data(0x00);
Data(0x00);
Data(0x0D);
Data(0xFF);
Data(0x00);
Data(0x00);
Data(0x0D);
Data(0x9F);
Data(0x19);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x00);
Data(0x0D);
Data(0xFF);
Data(0x00);
Data(0x00);
Data(0x0D);
Data(0xFF);
Data(0x00);
Data(0x00);
Data(0x0D);
Data(0x9F);
Data(0x19);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x00);
Data(0x0D);
Data(0xFF);
Data(0x00);
Data(0x00);
Data(0x0D);
Data(0xFF);
Data(0x00);
Data(0x00);
Data(0x0D);
Data(0x9F);
Data(0x19);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x00);
Data(0x0D);
Data(0xFF);
Data(0x00);
Data(0x00);
Data(0x0D);
Data(0xFF);
Data(0x00);
Data(0x00);
Data(0x0D);
Data(0x94);
Data(0x28);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x04);
Data(0x16);
Data(0xFF);
Data(0x00);
Data(0x04);
Data(0x16);
Data(0xFF);
Data(0x00);
Data(0x04);
Data(0x16);
Data(0x8F);
Data(0x35);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x04);
Data(0x20);
Data(0xFF);
Data(0x00);
Data(0x04);
Data(0x20);
Data(0xFF);
Data(0x00);
Data(0x04);
Data(0x20);
Data(0x8C);
Data(0x42);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x04);
Data(0x2A);
Data(0xFF);
Data(0x00);
Data(0x04);
Data(0x2A);
Data(0xFF);
Data(0x00);
Data(0x04);
Data(0x2A);
Data(0x8A);
Data(0x50);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x08);
Data(0x33);
Data(0x88);
Data(0x64);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x08);
Data(0x46);
Data(0xFF);
Data(0x00);
Data(0x08);
Data(0x46);
Data(0xFF);
Data(0x00);
Data(0x08);
Data(0x46);
Data(0x7C);
Data(0x67);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x44);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x44);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x44);
Data(0x6E);
Data(0x74);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x54);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x54);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x54);
Data(0x64);
Data(0x90);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x5E);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x5E);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x5E);
Data(0x5A);
Data(0x92);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x5F);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x5F);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x5F);
Data(0x52);
Data(0x94);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x61);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x61);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x61);
Data(0x4C);
Data(0x95);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x65);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x65);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x65);
Data(0x47);
Data(0x97);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x62);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x62);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x62);
Data(0x42);
Data(0x99);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x64);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x64);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x64);
Data(0x3E);
Data(0x9A);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x66);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x66);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x66);
Data(0x3A);
Data(0x9C);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x65);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x65);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x65);
Data(0x37);
Data(0x9D);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x68);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x68);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x68);
Data(0x34);
Data(0x9F);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x6A);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x6A);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x6A);
Data(0x32);
Data(0xA0);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x6B);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x6B);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x6B);
Data(0x2F);
Data(0xA2);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x70);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x70);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x70);
Data(0x2D);
Data(0xA4);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x72);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x72);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x72);
Data(0x2B);
Data(0xA6);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x75);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x75);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x75);
Data(0x29);
Data(0xA7);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x76);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x76);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x76);
Data(0x28);
Data(0xA8);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x79);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x79);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x79);
Data(0x26);
Data(0xAA);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x81);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x81);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x81);
Data(0x25);
Data(0xAC);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x81);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x81);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x81);
Data(0x23);
Data(0xAE);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x87);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x87);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x87);
Data(0x22);
Data(0xAF);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x89);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x89);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x89);
Data(0x21);
Data(0xB1);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x8D);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x8D);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x8D);
Data(0x20);
Data(0xB2);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x89);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x89);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x89);
Data(0x1F);
Data(0xB4);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x8E);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x8E);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x8E);
Data(0x1E);
Data(0xB6);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x93);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x93);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x93);
Data(0x1D);
Data(0xB8);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x98);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x98);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x98);
Data(0x1C);
Data(0xBA);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x95);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x95);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x95);
Data(0x1B);
Data(0xBC);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x95);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x95);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x95);
Data(0x1B);
Data(0xBC);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x91);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x91);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x91);
Data(0x1A);
Data(0xBE);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x9A);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x9A);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x9A);
Data(0x19);
Data(0xC0);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0xA8);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0xA8);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0xA8);
Data(0x19);
Data(0xC0);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0xA0);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0xA0);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0xA0);
Data(0x17);
Data(0xC6);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x02);
Data(0x2C);
Data(0xFF);
Data(0x00);
Data(0x02);
Data(0x2C);
Data(0xFF);
Data(0x00);
Data(0x02);
Data(0x2C);
Data(0x16);
Data(0xC9);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x02);
Data(0x45);
Data(0xFF);
Data(0x00);
Data(0x02);
Data(0x45);
Data(0xFF);
Data(0x00);
Data(0x02);
Data(0x45);
Data(0x14);
Data(0xD0);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x02);
Data(0x7F);
Data(0xFF);
Data(0x00);
Data(0x02);
Data(0x7F);
Data(0xFF);
Data(0x00);
Data(0x02);
Data(0x7F);
Data(0x11);
Data(0xDE);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x02);
Data(0xF0);
Data(0xFF);
Data(0x00);
Data(0x02);
Data(0xF0);
Data(0xFF);
Data(0x00);
Data(0x02);
Data(0xF0);
Data(0x0F);
Data(0xEB);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x03);
Data(0x54);
Data(0xFF);
Data(0x00);
Data(0x03);
Data(0x54);
Data(0xFF);
Data(0x00);
Data(0x03);
Data(0x54);

Command(0xDD);
Data(0x0B);
Data(0x0B);
Data(0x0B);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);

Command(0xDE);
Data(0x1C);

Command(0xE4);
Data(0x7F);
Data(0x7F);
Data(0x7F);
Data(0xEF);
Data(0xEF);
Data(0xEF);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0xFF);
Data(0xFF);
Data(0x00);
Data(0x00);
Data(0x00);

Command(0xED);
Data(0x0F);

Command(0xC7);
Data(0x00);

Command(0xC8);
Data(0xA4);

Command(0xD2);
Data(0xA7);

Command(0xE2);
Data(0x09);

Delay_ms(255);
Delay_ms(255);
Delay_ms(255);

Command(0xF0);
Data(0x7E);
Data(0x54);
Data(0x45);
Data(0x53);
Data(0x54);
Data(0x21);

Command(0x51);
Data(0x16);

Command(0x50);
Data(0x00);

Command(0xCE);
Data(0x80);
Data(0x00);
Data(0xE0);
Data(0x00);
Data(0x00);
Data(0x00);

Command(0xCD);
Data(0x06);
Data(0xC7);

Delay_ms(16);   //Delay 16ms or more

Command(0xCE);
Data(0x80);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);

Command(0xCD);
Data(0x06);
Data(0xC7);

Command(0xCD);
Data(0x00);
Data(0x00);

Command(0x35);
Data(0x00);

Command(0xE0);
Data(0xD0);
Data(0x00);

Command(0x29);
Data(0x00);

So is this an updates and corrected piece of example code?

look at the txt file you included and compare it to the code in the pdf file ... the txt file was created by copy and paste from the pdf file ... the problem is that the pdf file has the code arranged in four columns ... copy and paste of the four columns results in garbage data .... the code above matches the correct sequence in the pdf file

Ah okay I understand. Thankyou for correcting that.

Is the SPI communication method feasible? I have found a chip at present, and it seems that the driver can be transplanted directly. You can look at this chip.
https://nl.mouser.com/ProductDetail/Newhaven-Display/NHD-169-BREAKOUT?qs=wnTfsH77Xs6v7mYjAGElxw%3D%3D