SPARKY & SPECIAL EFFECTS ENGINEER.
  • Home
  • About Me
    • Contact
    • Qualifications
    • Links and Likes
    • Sailing
  • Q-Branch
  • Build services
  • Ford Ranger
    • The Ranger's Electronics
    • The 2018 rebuild
  • Electronics
    • Picaxe >
      • 08m2 Learning current detector
    • Arduino
    • Teensy
  • Projects
    • 1:72 Scale RC Submarine >
      • Radio Controlled submarine. The 2020 rebuild
    • PASIV Case (Inception)
    • UA-571-C Sentry gun (Aliens)
    • Starship bed >
      • Starship Electronics
      • The cockpit
      • Navigation console
      • The power supply
      • The self destruct system
      • Android App
    • TNAC >
      • TNAC - The 2020 update
    • Thunderbirds Intercom
    • The Pirate Ship
    • The Tardis
    • The Enchanted Forest
    • Christmas Vacation Advent House
    • Current projects
    • Misc
  • 3d Printing & CNC
    • RoStock Max V2 3d printer >
      • 3D Printer Enclosure
    • FlashForge 3d Printer
    • 3d printed CNC machine >
      • Wireless CNC controller
      • My CNC wiring
      • Joystick controller
      • Serial switch

Arduino programming

Those powerful little boards that eat up your evenings like pacman
UPDATE!!!    All hail Teensy

The world of Arduino's

Arduino's. 
They are amazing devices that run fast enough to operate digital displays, which is what I have been using them for.

I wanted some digital gauges for my pickup truck, so I decided to learn the Arduino programming system.
I purchased a selection of cheap LCD screens off of Ebay and away we went.

They are different from the Picaxe chips, in that you upload library's of commands and add them to your coding.
You can call upon the pre-programmed commands in the library and therefore obtain the desired result a lot quicker.
The hard work is done behind the scenes for you and saves you hours of programming.

As an example of this, the graphics are drawn on my gauges using a pre-loaded set of commands.
I simply ask it to draw a circle, or a line, or a box.  You give it the colour, the co-ords and it does the rest.
It still takes some serious programming to get the results you want, but nowhere near what it could have taken.
Picture

Above is my Arduino corner on my prototyping board.
I have an Arduino UNO (left) and and a Mega 2560 (right).
The Mega is the most powerful one and has a wealth of abilities that I will not go into here.
To be honest, I am still learning it myself.
Picture

Again, these processors are programmed using the free software on the web.
However, Arduino's are VERY popular, and there is a mountain of available data for them.
If you can think of a project, its highly likely that somewhere on the internet, a program has already been written that will accomplish 80% of what you need.
You can also buy a multitude of 'shields'.  These are boards that plug into the top of your Arduino board and give it extra functions.
The UNO and Mega boards have rows of header sockets along the tops that allow these boards to 'stack' on top.
The carry the essential supplies up through the boards and allow you to make very complex systems.
These shields can be motor drivers, sensors, GPS modules, radio modules, MP3 modules.... you name it.

You can also buy blank shields to make your own systems on.

I also have a few Mini Pro boards. These are great little devices and I used one to make the gear indicator for my truck.

The Arduino Pro Mini is a microcontroller board based on the ATmega328. It has 14 digital input/output pins (of which 6 can be used as PWM outputs), 6 analog inputs, an on-board resonator, and a reset button.

The ATmega328 has 32 kB of flash memory for storing code (of which 0.5kB is used for the bootloader). It has 2 kB of SRAM and 1kBs of EEPROM
I have not even touched the surface of the Arduino's abilities.
The gauge projects shown here are my first attempt at programming these processors.


If you want to read up on these devices, then a quick Google will return a huge amount of results.

Arduino's and TFT touchscreens

Well I purchased a 2.4" touch screen on Ebay and thought I would have a go at building a timer module (for a friend - hence their name obscured at the top of the TFT screen).

The screen came as a package with an Arduino Uno.
The screen shield plugged directly into the Uno and it didn't take too long to get the screen up and running.

However, it does have a few drawbacks.
The screen pretty much uses up all the inputs and output pins.
This leaves you only a few (4 in this case) to use as actual control lines to whatever you are controlling.

Picture

The better option would be to use an Arduino 2560 mega.
Far more input/output pins and only a few pounds more in price than the Uno.

It also has the advantage of having a much larger memory.
I have almost filled the program memory of the Uno, and that is after sacrificing the SD card reader feature, as that uses far too much memory.

If I use the Mega, then I can re-instate the handy SD card reader.
Picture

Now I have come up with a few ways around this issue.
I could add a few MCP230017 I/O expander chips
. A pair of these SPI controlled chips would allow me to control 16 extra inputs/outputs.

They also do this IC with I2c control, but I have SPI lines available, so I will use those.

There is also the 74HC595 Shift register IC.
That again could give me more pins (8 per chip).  They do a higher current versions too, but I think the above will be fine.

The only problem is really, you are making it more complicated than it really needs to be (plus a bigger PCB footprint)
Picture
Picture
Picture
But, as usual... its not that simple.  Yes, the TFT screen will plug into the Mega2560, but it does not work.
The port pins on the Mega are different, and so it does not work unless you twiddle around with it (for what turns out to be ages).

I found several reference pages on the internet for using a Mega with this screen, but they used a library that shifted the ports to make it work.  This leads to a speed reduction of 30 or 40%.  That isn't really acceptable.
It also meant opening various files within the libraries and editing them with Wordpad.  All a bit involved really.  Especially as it was not particularly clear what needed editing.

The Arduino forum

I did ask around the Arduino forum, but it leads to the usual short tempered answers from the big-headed knowledgable bods who don't have time for newbies.  You are just better off working it out for yourself.
I don't bother asking anything in the Arduino forum any more, 95% of the guys in the forum are just arrogant idiots.

I thought, forums were supposed to be helpful and guide for the newbies.  The Arduino forum is the exception to that rule.
Unless you are a top level programmer,  you will highly likely just get sarcastic, unhelpful crap, rather than the help you were looking for.
Someone will probably eventually step in, but the majority of the time, you are better off out of there.

'So why didn't you write the result into an array and then write a function to convert your data'.
If I knew how to do it DICKHEAD, I wouldn't be in here.

The other ones are, 'So why do you want to do that?',  or 'I don't see why you would want to do that'.   NOT the question thickhead.

I think I am on about my 15th Arduino forum user name (bounced through a VPN).  I usually either rage quit the thread (and the forum), or say what I think of these guys and get banned.

My advice? Look around on Google, you can work out nearly all issues with a little bit of detective work. 
The Arduino forum is a nasty little place full of nasty little people.
So I breadboarded the screen and began playing around.
Few hours later and we are sorted.  SD card, touchscreen all functioning.
The connections for the rear of the 2.4" touchscreen are shown here on the right. 

I used the Adafruit_GFX.h    graphics library, and the Adafruit_TFTLCD.h screen library.
You also need the TouchScreen.h and SD.h libraries if you want to use the touchscreen and SD card slot.

For those that are interested, the final connections to the Mega are listed below.

Arduino code and connections

Picture

--------------------------------------------------------
Make sure your SD card images
are saved as  320x240 pixels and
as BMP files.

 Screen             Mega2560   

                           
 3.3v                       3.3v   
 5v                            5V     
 GND                    GND         
 LCD_RD               A0       
 LCD_WR              A1     
 LCD_RS                A2   
 LCD_CS                A3      
 LCD_RST             A4       
 LCD_D0                22   
 LCD_D1                23       
 LCD_D2                24      
 LCD_D3                25       
 LCD_D4                26
 LCD_D5                27
 LCD_D6                28
 LCD_D7                29
 SD_SS                     53
 SD_D1                   51
 SD_D0                   50
 SD_SCK                52


-----------------------------------------------


If you measure the resistance between the A2 pin and pin 8 (low ohms range), you can add that reading into the touchscreen line to the right here and obtain a more accurate touchscreen result.

This code and set of connections enabled me to get the screen fully working without altering the content any of the library files.

Links to the libraries below.

Adafruit GFX.h Library
Adafruit TFTLCD.h Library
Adafruit Touchscreen.h library
SD.h library
SPI.h library
//2.4" Touchscreen to Arduino Mega2560

#include <Adafruit_GFX.h>          // Core graphics library
#include <Adafruit_TFTLCD.h> // Hardware-specific library
#include <TouchScreen.h>           //Touchscreen library
#include <SD.h>                                 //SD card library
#include <SPI.h>                               //SPI comms library (Serial Peripheral Interface) 

#define LCD_CS A3                         // Chip Select goes to Analog 3
#define LCD_CD A2                       // Command/Data goes to Analog 2
#define LCD_WR A1                     // LCD Write goes to Analog 1
#define LCD_RD A0                      // LCD Read goes to Analog 0
#define LCD_RESET A4

#define SD_CS 53
#define BUFFPIXEL 70               //Buffer for the SD card image reader

Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);

#define YP A3                                // must be an analog pin
#define XM A2                              // must be an analog pin
#define YM 23                              // can be a digital pin
#define XP 22                               // can be a digital pin

#define TS_MINX 150
#define TS_MINY 120
#define TS_MAXX 920
#define TS_MAXY 940

#define sdcard 52

TouchScreen ts = TouchScreen(XP, YP, XM, YM, 306);        //306 is the ohms reading between pins A2 and 8 (X axis).

//------------------------------------------------------------------------------------------------------------------------------------
void setup(void) {

tft.reset();
 uint16_t identifier = 0x9341;                //The graphics chip on my screen (yours may differ)
 tft.begin(identifier);  
 
  tft.setRotation(3);                                      //Sets the rotation of the display

  Serial.print(F("Initializing SD card..."));

  if (!SD.begin(SD_CS)) {
  Serial.println(F("failed!"));
  //return;
  }
  Serial.println(F("OK!"));

bmpDraw("Testimage.bmp", 0, 0);         //The name of the image you wish to display
delay(2000);
 
  #define MINPRESSURE 10                     //Set the touchscreen pressures
  #define MAXPRESSURE 1000
}
//------------------------------------------------------------------------------------------------------------------------------------
void loop(void) {

  digitalWrite(52, HIGH);
  TSPoint p = ts.getPoint();
  digitalWrite(52, LOW);

  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);

  if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {                //If the screen detects a press, then read the co-ords and check for button presses

 Serial.print("X = "); Serial.print(p.x);                                     //Display the X co-ordinate in the serial monitor
 Serial.print("\tY = "); Serial.print(p.y);                                 //Display the Y co-ordinate in the serial monitor
 Serial.print("\tPressure = "); Serial.println(p.z);            //Display the screen touch pressure in the serial monitor
//This is the loop you put your screen detection co-ords inside.
}

//----------------------------------------------------------------------

void bmpDraw(char *filename, int x, int y) {

  File     bmpFile;
  int      bmpWidth, bmpHeight;   // W+H in pixels
  uint8_t  bmpDepth;              // Bit depth (currently must be 24)
  uint32_t bmpImageoffset;        // Start of image data in file
  uint32_t rowSize;               // Not always = bmpWidth; may have padding
  uint8_t  sdbuffer[3*BUFFPIXEL]; // pixel in buffer (R+G+B per pixel)
  uint16_t lcdbuffer[BUFFPIXEL];  // pixel out buffer (16-bit per pixel)
  uint8_t  buffidx = sizeof(sdbuffer); // Current position in sdbuffer
  boolean  goodBmp = false;       // Set to true on valid header parse
  boolean  flip    = true;        // BMP is stored bottom-to-top
  int      w, h, row, col;
  uint8_t  r, g, b;
  uint32_t pos = 0, startTime = millis();
  uint8_t  lcdidx = 0;
  boolean  first = true;

  if((x >= tft.width()) || (y >= tft.height())) return;

  Serial.println();
  Serial.print(F("Loading image '"));
  Serial.print(filename);
  Serial.println('\'');
  // Open requested file on SD card
  if ((bmpFile = SD.open(filename)) == NULL) {
    Serial.println(F("File not found"));
    return;
  }

  // Parse BMP header
  if(read16(bmpFile) == 0x4D42) { // BMP signature
    Serial.println(F("File size: ")); Serial.println(read32(bmpFile));
    (void)read32(bmpFile); // Read & ignore creator bytes
    bmpImageoffset = read32(bmpFile); // Start of image data
    Serial.print(F("Image Offset: ")); Serial.println(bmpImageoffset, DEC);
    // Read DIB header
    Serial.print(F("Header size: ")); Serial.println(read32(bmpFile));
    bmpWidth  = read32(bmpFile);
    bmpHeight = read32(bmpFile);
    if(read16(bmpFile) == 1) { // # planes -- must be '1'
      bmpDepth = read16(bmpFile); // bits per pixel
      Serial.print(F("Bit Depth: ")); Serial.println(bmpDepth);
      if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed

        goodBmp = true; // Supported BMP format -- proceed!
        Serial.print(F("Image size: "));
        Serial.print(bmpWidth);
        Serial.print('x');
        Serial.println(bmpHeight);

        // BMP rows are padded (if needed) to 4-byte boundary
        rowSize = (bmpWidth * 3 + 3) & ~3;

        if(bmpHeight < 0) {
          bmpHeight = -bmpHeight;
          flip      = false;
        }

        // Crop area to be loaded
        w = bmpWidth;
        h = bmpHeight;
        if((x+w-1) >= tft.width())  w = tft.width()  - x;
        if((y+h-1) >= tft.height()) h = tft.height() - y;

        // Set TFT address window to clipped image bounds
        tft.setAddrWindow(x, y, x+w-1, y+h-1);

        for (row=0; row<h; row++) { // For each scanline...

          if(flip) // Bitmap is stored bottom-to-top order (normal BMP)
            pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
          else     // Bitmap is stored top-to-bottom
            pos = bmpImageoffset + row * rowSize;
          if(bmpFile.position() != pos) { // Need seek?
            bmpFile.seek(pos);
            buffidx = sizeof(sdbuffer); // Force buffer reload
          }

          for (col=0; col<w; col++) { // For each column...
            // Time to read more pixel data?
            if (buffidx >= sizeof(sdbuffer)) { // Indeed
              // Push LCD buffer to the display first
              if(lcdidx > 0) {
                tft.pushColors(lcdbuffer, lcdidx, first);
                lcdidx = 0;
                first  = false;
              }
              bmpFile.read(sdbuffer, sizeof(sdbuffer));
              buffidx = 0; // Set index to beginning
            }

            // Convert pixel from BMP to TFT format
            b = sdbuffer[buffidx++];
            g = sdbuffer[buffidx++];
            r = sdbuffer[buffidx++];
            lcdbuffer[lcdidx++] = tft.color565(r,g,b);
          } // end pixel
        } // end scanline
        // Write any remaining data to LCD
        if(lcdidx > 0) {
          tft.pushColors(lcdbuffer, lcdidx, first);
        }
        Serial.print(F("Loaded in "));
        Serial.print(millis() - startTime);
        Serial.println(" ms");
      } // end goodBmp
    }
  }

  bmpFile.close();
  if(!goodBmp) Serial.println(F("BMP format not recognized."));
}


uint16_t read16(File f) {
  uint16_t result;
  ((uint8_t *)&result)[0] = f.read(); // LSB
  ((uint8_t *)&result)[1] = f.read(); // MSB
  return result;
}

uint32_t read32(File f) {
  uint32_t result;
  ((uint8_t *)&result)[0] = f.read(); // LSB
  ((uint8_t *)&result)[1] = f.read();
  ((uint8_t *)&result)[2] = f.read();
  ((uint8_t *)&result)[3] = f.read(); // MSB
  return result;
}

Proudly powered by Weebly
  • Home
  • About Me
    • Contact
    • Qualifications
    • Links and Likes
    • Sailing
  • Q-Branch
  • Build services
  • Ford Ranger
    • The Ranger's Electronics
    • The 2018 rebuild
  • Electronics
    • Picaxe >
      • 08m2 Learning current detector
    • Arduino
    • Teensy
  • Projects
    • 1:72 Scale RC Submarine >
      • Radio Controlled submarine. The 2020 rebuild
    • PASIV Case (Inception)
    • UA-571-C Sentry gun (Aliens)
    • Starship bed >
      • Starship Electronics
      • The cockpit
      • Navigation console
      • The power supply
      • The self destruct system
      • Android App
    • TNAC >
      • TNAC - The 2020 update
    • Thunderbirds Intercom
    • The Pirate Ship
    • The Tardis
    • The Enchanted Forest
    • Christmas Vacation Advent House
    • Current projects
    • Misc
  • 3d Printing & CNC
    • RoStock Max V2 3d printer >
      • 3D Printer Enclosure
    • FlashForge 3d Printer
    • 3d printed CNC machine >
      • Wireless CNC controller
      • My CNC wiring
      • Joystick controller
      • Serial switch