Tuesday, October 29, 2019

ATtiny85-101 Initial Setup (with correct pre-installed bootloader)

ATtiny85-101 Initial Setup 
with correct pre-installed bootloader

Note: This procedure only work for some ATtiny85 board with proper pre-installed bootloader that can work with USB directly. 

Many boards from the market may not have correct version bootloader installed.  I use below link as my reference, but it does not work with the #1 board, I purchased from Amazon.  https://www.electromaker.io/blog/article/introduction-to-the-attiny85-19.  If so, see the note section for its solution.  Good luck!

Part: #1: https://www.amazon.com/gp/product/B07FCHFB85/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&psc=1 (it is with wrong version pre-installed bootloader.  It cannot work with USB connect directly.)

#2: https://www.amazon.com/gp/product/B07KVS4YGQ/ref=ppx_yo_dt_b_asin_title_o03_s00?ie=UTF8&psc=1 (it is with correct version pre-installed bootloader, that can work with USB cable directly.)

Setup Procedure:
Step 1: Open the Arduino application and click on File >> Preferences and past the following into the Additional Boards Managers URLs: dialog.
http://digistump.com/package_digistump_index.json 

Step 2: Go to Tools >> Board >> Boards Manager and from the drop-down menu select “Contributed”. and choose Select the “Digistump AVR Boards” and click Install.
In case it fails, try to install it manuelly with: C:\Users\**YOUR USERNAME**\AppData\Local\Arduino15\packages\digistump\tools\micronucleus\2.0a4\post_install.bat

Step 3: Go to Tools >> Board >> and select Digispark (Default - 16.5MHz) don’t worry about the Port.

Step 4: Copy and paste below program to Arduino IDE and save it.

Step 5: Make sure the ATtiny85 is unplugged from USB.

Step 6: Upload below code to ATtiny85.  Wait for below instruction to plug the ATtiny85 to USB cable.




Step 7: After the upload is completed, IDE will show below message.  P3 and P4 LED will blinking while code is uploading.


























Step 8: The upload is completed, and your ATtiny85 should running without problem.

Note:
10/25/2019 update: There is a problem with my ATtiny85.  As soon as I unplug it from USB, it FORGET its code.
10/29/2019 update: After burn a proper bootloader to the board, the above problem has been resolved.  See this link for solution.


Seeking for solution:
1. Such as program the ATtiny85 only, such as https://www.instructables.com/id/Programming-ATtinys-Micro-Controllers-With-Arduino/

2. Use the one with micro USB attached to its board such as https://www.amazon.com/gp/product/B07KVS4YGQ/ref=ppx_yo_dt_b_asin_title_o01_s00?ie=UTF8&psc=1

ATtiny85 Code in Arduino IDE
void setup() {
  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
}

void loop() {
  digitalWrite(0, HIGH);delay(200);
  digitalWrite(1, HIGH);delay(400);
  digitalWrite(2, HIGH);delay(600);
  digitalWrite(3, HIGH);delay(800);
  digitalWrite(4, HIGH);delay(1000);
  digitalWrite(4, LOW);delay(20);
  digitalWrite(3, LOW);delay(20);
  digitalWrite(2, LOW);delay(20);
  digitalWrite(1, LOW);delay(20);
  digitalWrite(0, LOW);delay(300);
}


Schematic:
Source: https://s3.amazonaws.com/digistump-resources/files/97a1bb28_DigisparkSchematic.pdf

ATtiny85 Datasheet

  • 8 pins
  • 8KB ISP flash memory
  • 512-Byte EEPROM
  • 512-Byte SRAM
  • 6 general purpose I/O lines
  • 32 general purpose working registers
  • One 8-bit timer/counter with compare modes
  • One 8-bit high speed timer/counter
  • USI
  • Internal and external Interrupts
  • 4-channel 10-bit A/D converter
  • Programmable watchdog timer with internal oscillator
  • Three software selectable power saving modes
  • DebugWIRE for on-chip debugging.
  • The device achieves a throughput of 20 MIPS at 20 MHz and operates between 2.7-5.5 volts

How to program ATtiny85 with Arduino 20191105

Objective: 
Setup Arduino Nano For ATtiny85 chip and Development Module Programming

FYI: I have tested ATtiny85 development module(see figure 1) with only using USB cable, but the first attempt fail by just following this link.  It forgets its code after power cycle.  It is because the installed bootloader in ATtiny85 was not installed properly.  After using below procedure, I have programmed ATtiny85 successfully.  For some development board (see figure 2), that can be program by USB cable without using Arduino, it is because it has proper version of bootloader installed before shipping from seller.

I fail setting up ATtiny85 for a long time just because of I did not familiar with the bootloader issue.  Hope this procedure help someone who encounter the similar problem today.  Good luck!
Figure 1.  Many of them do not have proper pre-installed bootloader.
Figure 2.

Material:

  • Arduino Nano
  • ATtiny85 chip or its development board
  • Wires
  • LED module


Top Level Procedure:

  1. Connect Arduino Nano and ATtiny85.
    1. Option 1: Connect to the ATtiny85 chip only
    2. Option 2: Connect to ATtiny85 development chip
  2. Setup ArduinoISP in Arduino Nano board.
  3. Setup and burn "Bootloader" to ATtiny85
  4. Upload program to ATiny85 by Arduino IDE via Arduino Nano


Detail Procedure:

Step 1:Connect Arduino Nano and ATtiny85:
Pin is for the ATtiny chip, PCINT is for the development module.


Pin layout form ATtiny85 Datasheet.
Program ATtiny85 chip.  Its pin 6 connect to an LED module.

Program a ATtiny85 on Micro USB Development Board.  Pin number (P0 ~ P5) is based on PINCT pin configuration.

Click link for Arduino Uno.

Step 2: Setup ArduinoISP in Arduino Nano Boar:

1. In IDE, File --> Reference.  In Additional Bord Manager URL enter "https://raw.githubusercontent.com/damellis/attiny/ide-1.6.x-boards-manager/package_damellis_attiny_index.json", and then click OK.

2. IDE: Tool --> Board --> Board Manager.  Search and install "attiny by David A. Millis"

3. IDE: Files-->Examples-->ArduinoISP-->ArduinoISP
4. IDE: Tool-->Board; choose "Arduino Nano", "ATmega328P", and its COM port.
5. Click "Upload" to program Arduino Nano.

Step 3: Burn Bootloader to ATtiny85:


  1. IDE: Tool-->Board-->Choose "Attiny 25/45/85"
  2. IDE: Tool-->Processor-->Choose "Attiny 85"
  3. IDE: Tool-->Clock-->Choose "Internal 8MHz"
  4. IDE: Tool-->Programmer choose "Programmer as ISP"
  5. Click IDE:Tool-->"Burn Bootloader"

Step 4: Upload program to ATiny85 by Arduino IDE via Arduino Nano

  1. IDE: File--:Example-->Basic-->choose "Blink"
  2. IDE: Change "LED_BUILTIN" to 1
  3. Upload using programmer. or write code to ATtiny85: Press "Shift" on keyboard and then click "Upload".
  4. Check with LED and see if pin 7 is blinking.
  5. Power cycle (unplug and re-plug usb) the board, and see if LED still blinking, if yes, you have successfully upload and burn code to ATtiny85.
  6. Done!
When "Shift" is pressed, and mouse over "Upload" button, you will see "Upload Using Programmer" on IDE.  It is important!!
Test Setup
Note: 
What if you forget to burn bootloader or do not having proper version bootloader installed.  You will see below error message when you try to write program to ATtiny85:




========================================
================ Side Project ===============
========================================

Build a ATtiny85 programming module (Side Project)
Use below table, and add LED on each channel, you can build programming module.  It is great addition to your inventory when you need to program ATtiny85 frequently.  It can be powered by external source.  Sometime, If Arduino Nano's pin are interference with ATtiny85, you may see some pins are acting funny.  The solution is using external power source and remove Arduino Nano.


Program ATtiny85 Chip
Programming ATtiny85 Development Module

Sunday, October 27, 2019

Work with DHT11 and 22 with Arduino without Using Library

Objective: 
Learn how to interact with both DHT11 and DHT22's, and how to extract its result from this device without using library in Arduino.
For example DHT11, pin arrangement are Vcc, Data, NA, GND
Proclaim: 
I choose a "hard" way to do this project just for learning a bit more about DHT11 and Arduino without using any external library.  If you looking for an effective way using DHT11, please do not use this example.  This example may confuse you if you do not fully understand what you are doing. 

Equipment: 

  • Nano Arduino
  • DHT11, DHT22
  • Oscilloscope

Schematic:
Standard setup with Arduino nano.  Connect 5V and GND between nano and DHT11.  On DHT11, connect its Vcc pin and data pine with 5k ohm resister.  Connect DHT11 data-pin to pin 2 on Arduino nano.  Oscilloscope measurement from nano pin 2.

DHT11 Data Structure:
  Its data pin need to be pulled down for >18ms by Arduino in order to trigger DHT11 to generate data.  After signal to be settled, DHT11 start sending 40 bits of data.  First 16 bit HR data, and next 16 bit temperature data, and the 8 bits of for Parity bit to verify data are received correctly.  See page 4 for detail.
Pull Down 20ms to trigger DHT11 to generated data.  The length of data is about 3ms.
Right after 20ms, it takes ~150us to be stabilized in my code.  The real data is starting from the third one.  The data we can see on screen is 00100

The first two pulses from Arduino are not data.  There are 40 bits data shown on this scope.  The length of data is ~3.7ms.  0 is about 28µs, and 1 is about 70µs.  Its data are 00100001 00000000 00010111 00000000 00111000.  HR data is the first two bytes.  Temperature are the 3rd and 4th byte.  The last byte is Parity byte. 
Above picture is copy from DHT11's datasheet.  See reference.



DHT11 Data Calculation Example:
  • Firs two byte are for humidity: 00100001 00000000 = 33%
  • The next two bytes are for temperature: 00010111 00000000 = 23°C
  • The last byte is parity byte: 00111000 = 56 (it is matched with 33 + 23).

Standard Final Test Result with "extract_data()"
When use "Display_Result()" with "Serial Plotter" in Arduino IDE.  This is a random result, not align with above result.
Reference:


Only first byte for HR, and third byte for temperature.
HR: 00100010 = 34, temperature : 00010100 = 20.  
Check sum: 00110110 = 00100010 + 00000000 + 00010100 + 00000000

Update on 10/27/2019, adding DHT22 calculation:
First and second byte for HR, and third and fourth byte for temperature.  Last byte for check sum.
HR: 00000001 01111001 = 377 =>/10>=>37.7%,
Temperature: 00000000 11100010=226=>/10=>22.6C, 
Check sum: 01011100 = 00000000+01111001+00000000+11100010
DHT22's data signal profile example.


From DHT22 datasheet page 3

Arduino code:
//DHT11 datapull by Arduino
//Author: Samson Yang
//Date: 10/26/2019
//It without using any libaray.  This is a very not effective way to pull data out of DHT11
//But, after familiar with how DHT11 and DHT22 work, the same experience can be applied to other device.
//read datasheet from
// http://www.produktinfo.conrad.com/datenblaetter/1400000-1499999/001405544-da-01-en-TEMP_UND_FEUCHTESENSOR_DHT11.pdf
//
int L=600;                        //Use 600 data point to pull data into matrix 
boolean data[1000];               //Need to be more then above L
boolean result[100];              //Need to be more then 40 
int resultcount=0;                //End result shoudl be 39.
int data_pin=2;                   //Set the data pin location
int extract_data_threadhold = 8;  //This threadhold between 0 or 1. It is the counts of high status between low voltage.
int DHT_type=22;                  //11 means DHT11, 22 means DHT22.  It will only be used at the end of data caculation

// Above setting is only good for Arduino nano.
// For faster board, you will need to change "extract_data_threadhold" and L.

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

void Get_Data(){
  for (int i = 0; i <= L; i++) {
    data[i]=digitalRead(data_pin);
    delayMicroseconds(5);
    }
}

void Display_Result(){
  for (int i = 0; i <= L; i++) {
    Serial.println(data[i]);
    data[i]=0;
    }
  Serial.println();
  delay(5000);
}

void loop(){
  readDHT();
  delay(1000);  
}
void readDHT() {
  // Go into high impedence state to let pull-up raise data line level and
  // start the reading process.  Pull from HIGH to LOW to tell DHT11 prepare sending dada out
  pinMode(data_pin, OUTPUT);
  //Pull up the data pin prepare for the next step
  digitalWrite(data_pin, HIGH);delay(250);  
  // First set data line low for 20 milliseconds to trigger DHT11 to start generate result.
  // Page 5 in datasheet, it needs >18ms.  
  digitalWrite(data_pin, LOW);delay(20); 

  // End the start signal by setting data line high for 40 microseconds.
  digitalWrite(data_pin, HIGH);
  delayMicroseconds(40);

  // Now start reading the data line to get the value from the DHT sensor.
  pinMode(data_pin, INPUT_PULLUP);  
  delayMicroseconds(50);  // Delay a bit to let sensor pull data line low, and wait till low before get data.   
  Get_Data();
  //Display_Result();  //You can use Serial Plot to see the data like oscolscope
  extract_data();  //Extract data and show end reult.
}

void extract_data(){
  int high=0;
  resultcount=0;
  
  for (int i = 0; i< L-1;i++){
    if ((data[i]==true)){high++;}
    if ((data[i]==false)){
      if (high>0){if(high > extract_data_threadhold){result[resultcount]=true;high=0;resultcount++;}}
      if (high>0){if(high < extract_data_threadhold){result[resultcount]=false;high=0;resultcount++;}}
      }
    }
  
  //for (int j = 0; j<= resultcount;j++){
  for (int j = 0; j< 40;j++){
    result[j]=result[j+1];
    Serial.print(result[j]);
    if (((j+1)/8.0)==int((j+1)/8.0)){Serial.print(" ");}//Add a space every 8 bits
    }  
  Serial.println();   
  //Prepare 2^i.  Arduino IDE do not understand ^ operant 
  double powerof2[16];
  powerof2[0]=1;
  for (int i=1;i<16;i++){
    powerof2[i]=1;
    for (int j=0;j<i;j++){
      powerof2[i]=powerof2[i]*2;  
    }
  }


  //Caculate for DHT11
  if (DHT_type==11){ 
    int startpoint=0;
    double HR=0, TM=0;  
    //Extract HR, temperature, and verify code
    for (int i=0;i<8;i++){
      HR=HR+powerof2[7-i]*(result[i]*1.0);
      TM=TM+powerof2[7-i]*(result[16+i]*1.0);
      //Serial.print("Debug:");Serial.print(" i=");Serial.print(i);Serial.print(" powerof2[15-i]=");Serial.print(powerof2[15-i]);Serial.print(", result[i]=");Serial.print(result[i]);Serial.print(" HR=");Serial.print(HR);Serial.print(" TM=");Serial.print(TM);Serial.println();
      //delay(500);
    }
    
    //Check SUM with 5th byte, ignore overflow
    int VR1=0,VR2=0,VR3=0,VR4=0,VRR=0,VR=0;
    for (int i=0;i<8;i++){
      VR1=VR1+powerof2[7-i]*(result[i]*1.0);    //1st byte
      VR2=VR2+powerof2[7-i]*(result[i+8]*1.0);  //2nd byte
      VR3=VR3+powerof2[7-i]*(result[i+16]*1.0); //3rd byte
      VR4=VR4+powerof2[7-i]*(result[i+24]*1.0); //4th byte
      VR=VR+powerof2[7-i]*(result[i+32]*1.0);   //VR byte      
    }
    VRR=VR1+VR2+VR3+VR4;
    if (VRR>=256)VRR=VRR-256;  //Remove overflow 
    HR=HR;
    TM=TM;
    
    Serial.print("DHT11, HR = ");Serial.print(HR,0);Serial.print("%, Temperature = ");Serial.print(TM,0);Serial.print("C.  Data status is ");
    if ((VRR-VR)==0){Serial.println("verified!");} else {Serial.println("NOT verified!");Serial.println();}    
  }
  //Caculate for DHT22
  if (DHT_type==22){ 
    int startpoint=0;
    double HR=0, TM=0;  
    //Extract HR, temperature, and verify code
    for (int i=0;i<16;i++){
      HR=HR+powerof2[15-i]*(result[i]*1.0);
      TM=TM+powerof2[15-i]*(result[16+i]*1.0);
      //Serial.print("Debug:");Serial.print(" i=");Serial.print(i);Serial.print(" powerof2[15-i]=");Serial.print(powerof2[15-i]);Serial.print(", result[i]=");Serial.print(result[i]);Serial.print(" HR=");Serial.print(HR);Serial.print(" TM=");Serial.print(TM);Serial.println();
      //delay(500);
    }
    
    //Check SUM with 5th byte, ignore overflow
    int VR1=0,VR2=0,VR3=0,VR4=0,VRR=0,VR=0;
    for (int i=0;i<8;i++){
      VR1=VR1+powerof2[7-i]*(result[i]*1.0);    //1st byte
      VR2=VR2+powerof2[7-i]*(result[i+8]*1.0);  //2nd byte
      VR3=VR3+powerof2[7-i]*(result[i+16]*1.0); //3rd byte
      VR4=VR4+powerof2[7-i]*(result[i+24]*1.0); //4th byte
      VR=VR+powerof2[7-i]*(result[i+32]*1.0);   //VR byte      
    }
    VRR=VR1+VR2+VR3+VR4;
    if (VRR>=256)VRR=VRR-256;  //Remove overflow 
    HR=HR/10.0;
    TM=TM/10.0;
    
    Serial.print("DHT22, HR = ");Serial.print(HR,1);Serial.print("%, Temperature = ");Serial.print(TM,1);Serial.print("C.  Data status is ");
    if ((VRR-VR)==0){Serial.println("verified!");} else {Serial.println("NOT verified!");Serial.println();}    
  }
}


Saturday, October 26, 2019

My First Curiosity Development Board Project

Objective: 
  • Familiar with Microchip Curiosity Development Board
  • Install and setup MPLAB X IDE
  • Familiar with DAC, CLC, TMR, PWM and C programming, and basic MPLAB IDE operation.
  • Confirm multiple independent function can be executed in PIC16F1619.

Project Initial Setup:
  1. Hardware:
    1. One "Curiosity Development Board", from Amazon, $20.
    2. One mini USB cable
    3. One Oscilloscope
  2. Software:
    1. Install MPLAB X IDE from https://microchipdeveloper.com/mplabx:installation
    2. Resource: https://www.youtube.com/watch?v=7MqyU0Lxj08

Start A New MPLAB Program (draft note only):
  1. Start MPLAB
  2. File--> Stand along project
  3. Enter device name, in my case, it is PIC16F1619
  4. Select "None" for debug header
  5. Select "Curiosity" in select tool window
  6. Select "XCB" in select compiler window.  Install one if missing.
  7. Provide project name, such as "My test code"
  8. Save "MyConfig.mc3" in "Save MCC Configuration File" window.
  9. Choose "PDIP20" in package pull down tab in "Pin Management Grid View".
  10. MPLAB is ready for programming

Project Objective:
  1. Setup "Saw Shape" signal generator with C code and DAC peripheral.
  2. General two clocks, they are 250KHz and 500Hz with TMR and PWM peripheral.  Setup up one switch to select signal with CLC peripheral but without using CPU's resource.
  3. About two signals process are run simultaneously and independently.
System Environment Setup:
Required Peripherals List

Setup Oscillator with "INTOSC..." and "1MHz".  This internal clock setting affect saw signal frequency directly.

Pin module setting -1

Pin module setting -2

Saw Shape Signal Generator:

Add a simple DAC code
Make sure check two check boxes.
DAC1OUT>>RA0, see the lock symbol in green box.


For 250K and 500 Hz Signal Switch: 
CLC1 setting, need assign "CLCIN0" and "CLCIN1" in above chart.
S1 >> RC4 >>CLCIN0 choose signal between CLCIN1 << PWM3 or CLCIN2<<PWM4
PWM3OUT>>CLCIN1, please note the right two corners' link symbol at RC3 (not show).

PWM4OUT>>CLCIN2, , please note the right two corners' link symbol at RC2 (not show).
CLC1OUT>>RC5, see lock symbol in green box.
Signal Flowchart, use RC4 to control switch to provide either 500Hz or 250KHz output to RC5.


Set clock range and precise Timer Period.  The Timer Period (ex, 2ms) define the timer frequency.
Set duty cycle and source of timer.
Set timer
Set duty cycle and source of timer, when Timer2 using "FOSC" as its source, PWM4 does not show any parameter in PWM parameter.  But, Timer2 using "FOSC/4" as its source, PWM parameters will be populated.  See PWM3 for comparison.  This issue seems not significant issue since both work either or not the PWM parameter has been populated in this window or not.  

Testing Microchip:
Ground: blue wire, RA0: white wire DAC output, RC5, blue wire timer/PWM signal output.
Yellow line: 230Hz saw signal has been generated by DAC and C code.  Its signal is not linear and very noise.  It could be a DAC bug from PIC16F1619.

Blue line: 250K Hz clock when S1 is off/not pressed.
Yellow line from generated by DAC which is quite noise.

S1 switch
Frequency has been dropped to 500Hz clock when S1 is pressed.

Programming Code:
#include "mcc_generated_files/mcc.h"
void main(void)
{
    // initialize the device
    SYSTEM_Initialize();
    uint8_t count=0;
    DAC1_Initialize();
    
    while (1)
    {
        for(count=0; count<=255; count++)
        {
            DAC1_SetOutput(count);
            //__delay_ms(1);
        }
    }
}

Summary:
This 20$ Curiosity Development Board is a very a very different but a powerful  board compare to Arduino.  You can set and execute multiple functions on the same chip and run interdependently.  Many functions can be operated without using CPU resource too. 

My favor peripheral are Timer, PWM and CLC.  They can be set easy without code, and run very fast.  My less favor part is DAC because it is very slow and very noise at the same time.  The worst part is poor signal linearity issue.

I am happy having this board, and will use it on my future project.  However, the first time I try it, I almost give up and return it back to Amazon within the same day.  Here is why:

  1. Cannot find much information on book or internet about this board.
  2. MPLAB X IDE is very complicate.
  3. Many operation concept are new compare to Arduino's.
  4. It is for advance user.  Very steep learning curve.  
  5. Cannot follow some examples since it demos with a different board from Microchip website.  Some peripheral's name, and option are different in their demonstration.
  6. User much familiar with C programming coding.
  7. User must familiar with logical gate.
  8. User must has sufficiency tool to work with this board, such as oscilloscope and etc.
  9. Microchip company do not provide example or detail description on many peripheral such as AT, CCP, CRC, CWG, ZDC, MSSP, FVR and etc.
PIC16F1619 is a power chip, it opens a new application opportunity to me such as HDMI signal handling, and different clock signal source.  But NOT recommend for beginner unless you can find help from experienced user. 

This is my first time using this board.  When writing this blog, I only have about two days trial and error experience on this board.  If you see error, please do not hesitate let me know.  Thanks.  

Resource: