How to connect ATtiny85 for In-system Programming (ISP) while already hooked up to sensors and output devices?

Hi Forum, regarding In-system Programming (ISP), Wikipedia says: "... the ability ... to be programmed while installed in a complete system ..."

I'm trying to achieve such a "complete system" for ATtiny85 chip with sensors and output devices attached. But it is not clear to me how I can permanently integrate a programmer in this setup where the ATtiny85 is hooked up with most pins already connected. If it is at all possible, please advise on how to proceed, or point me to a project where this has already been used. Any advise on alternatives or further help is highly appriciated.

Background

As a new member in the community, who has a programming background but is novice at electronics, I'm using a Nano based ISP programmer to upload sketches to ATtiny85. I have it working like this.

As my first real project, the details are captured in a series of blog posts , if you're interested.

For the schematics, hope I got this right. Please let me know if there are any flaws. This electronics stuff is all very new to me.

Currently I have to take out the ATtiny85 from the programmer breadboard and move it onto a test breadboard each time the .ino file is changed, to see if it works. Which is cumbersome and, if I understand it correctly, exactly the opposite of in-system programming.

The programmer is connected from Nano ICSP header to the ATtiny85 on pins 4, 5, 6, 7 and 8. And from Nano D10 to ATtiny85 pin 1.

This is the test board for a Blink.ino with LED pin set to 3 (PB3 = physical pin 2 on ATtiny85).

The pins for ICSP are still available. So presumably, I could move the wires over from the programmer and program directly to this test board.

But my question applies to any setup where pins to be used for ICSP are already taken by sensors or output devices. To give an example, this is a current test setup, where I display temperature and humidity readings on an LCD screen. The button is to wake the LCD from screensaver state that kicks in after a minute.

A novice attempt at schematics. Please advise on how to improve.

Pins 5 and 7, to be used for programming the ATtiny85, are already in use. How would I hook up the programmer here when several pins are already taken for the DHT11 and LCD screen? Is it at all possible?

To be complete, the programmer uses Arduino IDE's ArduinoISP.ino from File -> Examples -> 11. ArduinoISP -> ArduinoISP

The temperature/humidity setup uses this code.

// ------------------------------------------------------------
// DHT11 with LCD via TinyLiquidCrystal_I2C
// Read temperature and humidity from DHT11 sensor.
// 
// References:
// https://www.make-it.ca/i2c-lcd-display-on-arduino/
// https://create.arduino.cc/projecthub/pibots555/how-to-connect-dht11-sensor-with-arduino-uno-f4d239 (Old links to arduino project hub are broken since recent update)
// https://forum.arduino.cc/t/print-degree-symbol-on-lcd/19073
// https://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html#ga060c998e77fb5fc0d3168b3ce8771d42
// ------------------------------------------------------------

// Include the liquid crystal I2C library
#include <TinyLiquidCrystal_I2C.h>

// Include the DHT library
#include "TinyDHT.h"

#define DHTPIN 4
#define DHTTYPE DHT11 // #define DHTTYPE DHT22 // if you have this sensor
#define BUTTONPIN 3

// Create DHT object
DHT dht(DHTPIN, DHTTYPE);

// Set the I2C address to 0x27 for the LCD screen.
// Set to 16 characters and 2 lines. Adjust to (0x27,20,4) for 20x4 LCD
TinyLiquidCrystal_I2C lcd = TinyLiquidCrystal_I2C(0x27,16,2);

const int serialSpeed = 9600;

unsigned long startScrollMillis;
unsigned long startReadMillis;
unsigned long startScreenSaveMillis;
unsigned long screenSaveOffMillis;
boolean screenSaver = false;
unsigned long currentMillis;
const unsigned long lcdScrollDelay = 600;
const unsigned long sensorReadDelay = 10000;
const unsigned long lcdScreenSaveMillis = 60000;
unsigned long diff = 0;
String readString;
String f;
String c;
String h;
String r;
String hic;
String hif;
char buffer[10];
int buttonState = 0;
int previousState = 0;

void setup() {
  //Serial.begin(9600);
  // Initialize the pin for the button
  pinMode(BUTTONPIN, INPUT);
  // Initialize the DHT sensor
  dht.begin();
  // Initialize the LCD display
  lcd.init();
  // Switch off display for a short while
  lcd.noDisplay();
  lcd.noBacklight();
  delay(2000);
  // Turn on the display:
  lcd.display();
  lcd.backlight();
  delay(1000);
  // Display startup message
  lcd.setCursor(1, 0);
  lcd.print("DHT11  LCD I2C");
  delay(3000);
  lcd.setCursor(1, 1);
  lcd.print("fotografeer.nl");
  delay(4000);
  lcd.clear();
  startReadMillis = 0;
  startScreenSaveMillis = 0;
}

void loop() {
  // Don't read sensor and don't update display if screen saver is on.
  // Otherwise wait a while between each read/screen refesh.
  currentMillis = millis();
  diff = currentMillis - startReadMillis;
  if (currentMillis - startReadMillis >= sensorReadDelay && !screenSaver) {
    // Read Humidity
    float humidity = dht.readHumidity();
    h = dtostrf(humidity, 5, 1, buffer);
    // Read Temperature in degrees Celsiuse
    float celsius = dht.readTemperature();
    c = dtostrf(celsius, 5, 1, buffer);
    // Read Temperature in degrees Fahrenheit
    float fahrenheit = dht.readTemperature(true);
    f = dtostrf(fahrenheit, 5, 1, buffer);
    // Clear display
    lcd.clear();
    // Check if any reads failed and exit early (to try again).
    if (isnan(humidity) || isnan(celsius) || isnan(fahrenheit)) {
      lcd.setCursor(0, 0);
      lcd.print("error");
      return;
    }

    // Display Temperatures
    lcd.setCursor(0, 0);
    lcd.print(c);
    lcd.setCursor(5,0);
    lcd.print((char)223);
    lcd.setCursor(6,0);
    lcd.print("C");

    lcd.setCursor(9, 0);
    lcd.print(f);
    lcd.setCursor(14,0);
    lcd.print((char)223);
    lcd.setCursor(15,0);
    lcd.print("F");

    // Display Humidity
    lcd.setCursor(0, 1);
    lcd.print(h);
    lcd.setCursor(5,1);
    lcd.print("%RH");
    startReadMillis = currentMillis;
  }

  // Get current milliseconds
  currentMillis = millis();

  // Read current button state (PRESSED/HIGH or RELEASED/LOW)
  buttonState = digitalRead(BUTTONPIN);
   
  // If button pressed, turn screensaver off
  if (buttonState == HIGH && screenSaver) {
    // read the state of the pushbutton value:
    lcd.clear();
    lcd.backlight();
    lcd.display();
    screenSaver = false;
	screenSaveOffMillis = currentMillis;
  }

  // Turn LCD screen saver mode on, when screen saver timer has expired
  if (currentMillis - screenSaveOffMillis >= lcdScreenSaveMillis && !screenSaver) {
	screenSaver = true;
    lcd.clear();
    lcd.noBacklight();
    lcd.noDisplay();
  }
}

wok

1 Like

What I sometimes do is 2 rows of 3 pinheaders on PB0, PB1 and PB2. Normally these are bridged by 3 jumpers. When programming I pull the jumpers off, and connect the ISP wires to those pins. Then one additional pinheader for the reset pin and if not already present pinheaders for VCC and GND.

1 Like

You would arrange for the LCD to be switched out of the circuit while you program it. Then switch the LCD back when you want to run the code.

1 Like

Thanks, @ZX80, @hmeijdam and @Grumpy_Mike. From you answers it is clear that I need some kind of switching mechanism. Will look into that. Using a DIP switch or additional pinheaders with jumpers both look viable solutions. Will use a bigger breadboard to test such a setup.

Just thinking out loud here: The programmer in me would want to automate it further, rather than to manually change DIP switches or jumpers. Upon detection of the Nano programmer being powered up/down, I would like to have an automated switching between two state that each uses its own set of wires.

  1. Programming (using wire set to Nano programmer)
  2. Normal Operation/Testing (using wire set to sensors/output devices)

Not sure what could be used to switch between the sets of wires. A relais on each wire could probably work. But it would be overdoing it, as the design needs to be compact. Don't know of any other components that could be used. Is there something like a programmable DIP switch or an IC that one could use to switch between sets of wires?

Yes it is called a multiplexer.
There are two basic types, digital and analogue. The analogue type can function as a two way (direction) device.

You need one with two inputs and one output for each line to switch between the two.
see
https://www.electrical4u.com/multiplexer/

1 Like

Well, at a minimum, you just need to connect or disconnect the circuit components to/from the ICSP related pins on the 85. This will date me, but a CD4066 analog switch would let you connect four lines. But you would need to switch the control inputs in some automatic way.

1 Like

I'm going to suggest you sidestep the problem and simply not use the Tiny85. Anything you add will be more complex than just using a more capable chip. A Mega328 in a QFP package is probably physically smaller than a Tiny85 in a DIP and has about 10x the I/O.

2 Likes

Thanks for your feedback @Grumpy_Mike, @ShermanP and @cedarlakeinstruments.

All 3 options are new to me and give me lots to consider and study up on. Also, I haven't worked out how to detect power on/off on Nano yet. For now a manual switching mechanism will suffice, while I learn more about multiplexer, CD4066 and Mega328.

"Anything you add will be more complex than just using a more capable chip."

Fair point. What you are suggesting is to use a chip with enough pins, so there is no need to switch, right? Then the sensors, output devices and ICSP wires would be able to all have their own dedicated pins.
Note that I'm a novice at things regarding electronics. It toke me quite some time to figure out how to program the Tiny85. I guess it will be easier now my programmer is in place. Will it be a matter of connecting ICSP and RST wires to different pins for programming a different chip? Or is there more to consider?
For the temperature/humidity setup, I will stick with Tiny85 for now. For future projects, using a more capable chip looks like the way to go when ISP is required.

Or you can migrate to the newer Attiny generation supported by MegatinyCore
They are cheaper and better and can be programmed via the single wire UPDI protocol.
What's the catch? They are SMD only (but not too small), so you will need to solder them on adapter plates for using them in a breadboard.

2 Likes

I am in complete agreement with @cedarlakeinstruments. If you need more than a couple of jumpers/dip switches to allow in-circuit programming, then you would be better off switching to an MCU with more pins. Going to the lengths of using multiplexers just to allow in-circuit programming is definitely going too far in my opinion.

The way I would approach your project would be, I think, as follows. Everyone please comment if you think this won't work.

Build your prototype on breadboard, with your sensor, LCD and ISP header all connected up, assuming there will be no problem having both connected at the same time.

Test uploading code. In fact, test uploading several different codes, blink sketch etc. If that works consistently, then no problem. If you get failures during the upload, disconnect the components connected to the ISP pins, one at a time, until upload works successfully. Chances are only one connection will turn out to be the culprit.

Can that connection use a different pin, and is there an unused pin or a pin used for some other connection that could be swapped to the ISP pin? Try a few pin swaps or moves. Chances are you can find some configuration where ISP upload works.

If you can't find any swap or move that solves the problem, put a jumper or dip switch on that connection to allow you to switch between upload and run modes.

I only suggest this approach having reviewed the components connected to the attiny. In this case, both use pull-up resistors (the 10K shown for the temp sensor, and the pull-up resistors that are built into the i²c backpack on the LCD) and they can only pull the attiny pins down, and they will only do that for very short pulses because they are transmitting data, so unlikely to cause damage. In both cases, these devices will only ever do that if they are triggered to do so by the attiny, and the chances are that just won't happen because they use different data protocols to in-circuit programming. I think the chances are very low that the signals transmitted by ISP programming could trigger one of the other components to think it has received a request for data and try to respond.

2 Likes

Thanks, good to know these are out there and also fall in the category "more capable chips". I don't think soldering is for me. Don't have the equipment and skills. But I could try to persuade friends to do it for me.
This UDPI sounds very interesting. Will also look into that.

So actually you are saying that electronics is not for you. You need to either acquire the skill or dump the hobby. Maybe take up knitting.

May I remind you of the forum guidelines on https://forum.arduino.cc/faq:

This is a Civilized Place for Public Discussion

Please treat this discussion forum with the same respect you would a public park. We, too, are a shared community resource — a place to share skills, knowledge and interests through ongoing conversation.

These are not hard and fast rules, merely guidelines to aid the human judgment of our community and keep this a clean and well-lighted place for civilized public discourse.

Improve the Discussion

Help us make this a great place for discussion by always working to improve the discussion in some way, however small. If you are not sure your post adds to the conversation, think over what you want to say and try again later.

The topics discussed here matter to us, and we want you to act as if they matter to you, too. Be respectful of the topics and the people discussing them, even if you disagree with some of what is being said.

One way to improve the discussion is by discovering ones that are already happening. Spend time browsing the topics here before replying or starting your own, and you’ll have a better chance of meeting others who share your interests.

Be Agreeable, Even When You Disagree

You may wish to respond to something by disagreeing with it. That’s fine. But remember to criticize ideas, not people. Please avoid:

  • Name-calling
  • Ad hominem attacks
  • Responding to a post’s tone instead of its actual content
  • Knee-jerk contradiction

Instead, provide reasoned counter-arguments that improve the conversation.

For normal operations and testing, 6 is the only free pin.
Pin 5 (SDA) and 7 (SCL) should best match up with LCD SDA and SCL.
So there is no room left to move pins around.
Made an overview of all connections for both states:

tiny85 Pin Button DHT11 LCD ICSP (Nano) GND VCC
1 RESET D10
2 PB3 yes
3 PB4 Data
4 GND yes
5 PB0 (SDA) SDA MOSI
6 PB1 MISO
7 PB2 (SCL) SCL SCK
8 VCC yes

There are 2 pins where there is a potential conflict. Pins 5 and 7 are used by both LCD and ICSP. When I moved the RST, MOSI, SCK and MISO over to the test board, the LCD didn't display the temp/humidity any more. Just a blank screen. I don't want to risk damaging it, since it is the only one I currently have.

By now I have come to the conclusion that combining ICSP and the temp/humidity setup is not easily achievable. Since the software code is mostly done, I will forgo my attempts on implementing ISP for this example.

For future projects were ISP is required, I will adhere to the advice from @cedarlakeinstruments and go for a more capable chip that offers more pins. Then ISP, sensors and output devices can all have their dedicated pins. And then there is also no need for detection if the ISP programmer is switched on or off.

Thanks everyone, learned a lot from all your advice and alternatives.

If you are looking for a workaround, where you need to often switch between programming an ATTiny85 and testing it in a test setup, you could use a ZIF socket in between the two.

Setup could look something like this

With this schema

I've had this issue in the past. The pcb was in an inaccessible enclosure. I wired the affected paths to a DB15 connector mounted on the enclosure panel with 24AWG. Then I made a mating shorting plug to make the connections needed during operation.

When I needed to update the code, I unplugged that shorting connector and plugged my programmer into the DB15, never opening the enclosure.

1 Like

For those who do want to use the attiny85 (or any small mcu for that matter):

  1. Have a zif socket on both your programmer and your prototype, swapping isn't that big of a deal. I even leave the programmer connected when swapping the ATtiny (and use the breadboard power supply switch on the other setup).
  2. There's probably a lot of code which you can test on an Arduino or cheap clone (or even one of those online simulators).
  1. Use functions so you can test discrete parts of your sketch
  2. If you, like me when I started, find yourself swapping the ATTiny like there's no tomorrow you're not developing but just trying things until it works :slight_smile: .

Dropped in for the topic, but on thought I'd address soldering: I went into software because as a teen I couldn't solder for the life of me. I'm now retired, and had another go at soldering. Very satisfying. I'd recommend getting a soldering/hot-air station and a USB microscope.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.