Quantcast
Channel: Hardware testing – Arduining
Viewing all 20 articles
Browse latest View live

Using the Linear Sensor Array TSL201R with Arduino

$
0
0

Dealing with linear Sensor Arrays is not easy. After some research in the web, found some experiments with TSL1401, TSL202R and TSL201R, many of them without a happy ending.

My intent is to find out how to do simple image processing of Linear Sensor Arrays using the Arduino.

This will open the path to develop some interesting experiments and applications:

-Line Follower Robots.

-Optical Flow Sensor (to sense movement in robots and autonomous vehicles).

-Laser Range Finders.

-Imagen Scanners (Barcode, character recognition etc.)

-Position Sensors.

-Objet Detection and Objet Counting.

-Objet Shape Identification and Analysis.

-Light Spectrum Analyzers.

-Etc…

After reading the (64×1) linear Sensor Arrays TSL201R manual…

tsl201r-fingertip

…decided to buy some DIP-8 versions (package discontinued) in Aliexpress.com, (breadboard friendly).

AMS produces the SMT version,  The TSL201CL.

This is the wiring diagram:

TSL201R_Wiring

Arduino NANO, solid wires (AWG#22) and an adequate breadboard  for the job.

TSL201R_Test_01_noFilter

The Arduino is relatively slow to scan and read this sensor. To solve this limitation the integration time is increased

by reducing the incoming light. A pinhole approach is implemented with a tiny black box (a relay case).

Pinhole cameras using  PCB Relay’s cases:

tsl201r-test-panels

Because the small hole, more integration time is needed.

The projected image field of view can be estimated using geometry…

pinhole-image-size-3

In the Sketch only one pixel is readed in each scan. The image is completed after 1+64 scans.(first is discarded)
First scan is repeated to permit a complete integration period.
The Pixel integration Period is adjustable using a potentiometer in the analog channel 1.

/*TSL201R_Scanning.ino Arduining 26 MAR 2014

Linear Array Sensor TSL201R (TAOS) is now AMS:
  -64 x 1 Linear Sensor Array 200 DPI

-Sketch used with the Arduino NANO.
  Data is Send at 115200 bauds (ASCII messages ending with CR and LF)
  One frame (64x1 image) has the followinf format:
      >5890    Indicates the integration period in microseconds.
      843      this value is discarded.
      234      value of the pixel 1
      242      value of the pixel 2
       .         .
       .         .
      245      value of the pixel 64

-Reading only one pixel in each scan.
-The image is completed after 1+64 scans.(first is discarded)
-First scan is repeated to permit a complete integration period). 
-Pixel integration Period is adjustable (potentiometer in analog channel 1).

*/

#define CLK     2
#define SI      3
#define VOUT    0   //pixel intensity in the analog channel 0
#define INTVAL  1   //integration time adjust in the analog channel 1.
#define PIXELS  64

int intDelay;      //Integration Period = (intDelay + 535 ) microseconds.
int Value;         //pixel intensity value.

void setup(){
  pinMode(CLK, OUTPUT);
  pinMode(SI, OUTPUT);
  digitalWrite(CLK, LOW);
  digitalWrite(SI, LOW);

//  Serial.begin(9600);
  Serial.begin(115200);
  Serial.flush();
}



void loop(){
  intDelay=1+analogRead(INTVAL)*10;  //read integration time from potentiometer.
  Serial.print(">");                //Mark the start of a new frame
  Serial.println(intDelay + 535);   //Send Integration Period in microseconds.
//  delay(8);     // used with 9600 bauds
  delay(2);     // used with 115200 bauds

  readPixel(0);                     //the first reading will be discarded.
  delayMicroseconds(intDelay);

  for(int i=0;i<PIXELS;i++){
    readPixel(i);
    delayMicroseconds(intDelay);    //Delay added to the integration period.
  }
}

//------------------ Send the intensity of the pixel serially -----------------
void readPixel(int pixel){
  digitalWrite(CLK, LOW);
  digitalWrite(SI, HIGH);         
  digitalWrite(CLK, HIGH);
  digitalWrite(SI, LOW);
 

  for(int i=0;i<pixel; i++){    //Clock pulses before pixel reading
    digitalWrite(CLK, LOW);
    digitalWrite(CLK, HIGH);    //Select next pixel and reset integrator of actual pixel.
  }

  Value = analogRead(VOUT);
  Serial.println(Value);
//  delay(8);       //used with 9600 bauds
  delay(1);         //used with 115200 bauds
  for(int i=0;i<=(PIXELS-pixel); i++){    //Clock pulses after pixel reading.
    digitalWrite(CLK, LOW);
    digitalWrite(CLK, HIGH);    //Select next pixel and reset integrator of actual pixel.
  }
}

The application in Progressing shows the illuminance of each pixel sent by the arduino.

Integration time and frames per second (FPS) are also presented.

TSL201RView_06e

Here is the Processing code Pro_TSL201RViewer.pde :


/*Pro_TSL201RViewer.pde    28 AUG 2015

Processing Viewer for the Linear Array Sensor TSL201R (AMS):
  64 x 1 sensors (200 DPI)

Data is received at 115200 bauds (ASCII messages ending with CR and LF)
One frame (64x1 image) has the followinf format:
      >5890    Indicates the integration period in microseconds.
      543      this value must be discarded.
      234      value of the pixel 1
      242      value of the pixel 2
       .         .
       .         .
      245      value of the pixel 64

Works with the Sketch:TSL201R_Scanning.ino in the Arduino.    
  
------------------------------------------------------------------------------*/
//---------------- Labels -----------------------------------------------------
String    heading = "TSL201R Wiewer";
String    credit  = "Arduining.com";
//------------------------- Graph dimensions (constants) ----------------------
//System variables width and height are defined with size(width,height) in setup().

int       leftMargin=   80;   //from Graph to the left margin of the window
int       rightMargin=  80;   //from Graph to the right margin of the window 
int       topMargin=    70;   //from Graph to the top margin of the window.
int       bottonMargin= 70;   //from Graph to the botton margin of the window.
//-------------------- Colors -------------------------------------------------
final  color  frameColor =  color(0,0,255);    // Main window background color.(Blue)
final  color  graphBack =   color(0,0,128);    // Graphing window background color. (Dark black)
final  color  borderColor=  color(128);        // Border of the graphing window.(grey)
final  color  barColor=     color(255,255,0);  // Vertical bars color. (yellow)
final  color  titleColor=   color(255,255,0);  // Title color. (yellow)   
final  color  textColor=    color(180);        // Text values color. (grey)  
//-------------------- Serial port library and variables ----------------------
import    processing.serial.*;

Serial    myPort;
boolean   COMOPENED = false;      // to flag that the COM port is opened.
final  char  LINE_FEED=10;        //mark the end of the frame.
final  int  numRecords=3;         //Number of data records per frame.
String[]  vals;                   //array to receibe data.
String    dataIn= null;           //string received
int       pixelCount= 64;
int       lightIntensity;
int       Integration= 0;         //Integration period in milliseconds
int       timeStamp;              // used to calculate frames per second (FPS). 
int       lastTimeStamp;          // used to calculate frames per second (FPS). 
float     framePeriod=0;          // used to calculate frames per second (FPS). 
PFont     font;
int       graphBase,graphWidth,graphHeight;

//-------- Variables to allocate the parameters in "settings.txt" --------------
String    comPortName;
float     Gain= 1;

//-------- Default content of "settings.txt" (one parameter per line) ----------
String[] lines = {
                 "Port:COM4",      //Serial Port
                 "Gain:1"};        //Gain (data amplification)

//------------------------------------------------------------------------------
//  setup
//------------------------------------------------------------------------------
void setup(){
  
  size(800,600);        // setting system variables width and height.
  
  FillParams();         //Read "settings.txt" an fill the values.
  PortManager();        //Deal with the port selection and opening.

  graphBase= height-bottonMargin;
  graphHeight= height-bottonMargin-topMargin; 
  graphWidth= width-leftMargin-rightMargin;

  font = createFont("Arial",12);

  timeStamp= millis();
  lastTimeStamp = timeStamp;

  background(frameColor);     // Main window background color.
  clearGrahp();
  showLabels();
  showParams();               // Display variables (usefull for debugging)
}

//==============================================================================
//  draw (main loop)
//==============================================================================
void draw(){

  while (myPort.available() > 0) {
    dataIn = myPort.readStringUntil(LINE_FEED);
    if (dataIn != null) {
      print(dataIn);                //show dataIn for debugging
      dataIn= trim(dataIn);         //removes spaces, CR and LF.
      PlotData();
      showParams();
    }
  }
}

//------------------------------------------------------------------------------
//Plot the incoming data in the Graph.
//------------------------------------------------------------------------------
void PlotData(){

  if (dataIn.charAt(0)=='>'){ 
    Integration= int(dataIn.substring(1,dataIn.length())); // removes '>'.
    timeStamp= millis();             //calculate period between frames.
    framePeriod= 1000/float(timeStamp - lastTimeStamp);
    lastTimeStamp= timeStamp;
    println("         (" + Integration +")");   // print Integration period.
    pixelCount=-2;            //reset pixel counter (-2 to skip first reading).
  }

  else if((pixelCount >= 0) &amp;&amp; (pixelCount < 64)){
    lightIntensity= int(dataIn)/2;
    println("light= " + lightIntensity);

// ------- Clear the pixel region. -------------------
    noStroke();                 //no border
    fill(graphBack);            //Dark blue background
    rect(1+leftMargin +(graphWidth/64)*pixelCount, graphBase, (graphWidth/64)-2, 1-graphHeight);

// ------- Draw pixel intensity value as a vertical bar. -------
//    strokeWeight(1);
//    stroke(0);                //black border
    noStroke();
    fill(barColor);              //Color of the vertical bars
    rect(1+leftMargin +graphWidth*pixelCount/64, graphBase,(graphWidth/64)-2, -constrain(lightIntensity*Gain, 0, graphHeight-1));
  }
  pixelCount++;       //pointer to draw next pixel.
  println("--------" + pixelCount + "-"); //show pixel for debugging
}

//------------------------------------------------------------------------------
//Display diferent values for debugging.
//------------------------------------------------------------------------------
void showParams(){
  noStroke();                 //no border
  fill(frameColor);           //Blue background
  rect(1,height, width-250, 1-bottonMargin);  //Clean parameters region.

  textFont(font,18);
  textAlign(LEFT,BOTTOM);    //Horizontal and vertical alignment.
  fill(textColor);

//---------- Show COM Port -----------------------------
  if (COMOPENED){
    text(lines[0],20, height-15);                          //Show the COM port.
    text("Gain: "+ Gain ,150, height-15);                  //Show Vertical Gain.
    text("Integration: " + Integration,270, height-15);    //Show Integration Period.
    text("FPS: "+ nf(framePeriod, 1, 1) ,450, height-15);  //Show frames Per Second (FPS)
  }
  else {
    fill(255,0,0);
    text(lines[0]+" not available",20, height-15);   //COMM port not available.
  }
}

//------------------------------------------------------------------------------
//Clear graph area.
//------------------------------------------------------------------------------
void clearGrahp(){

  stroke(borderColor);        //Graph border color.(gray)
  fill(graphBack);            //Dark Blue background
  rect(leftMargin, graphBase,graphWidth,-graphHeight);
}
  
//------------------------------------------------------------------------------
//Write the labels.
//------------------------------------------------------------------------------
void showLabels(){
  textAlign(CENTER,CENTER);
  textFont(font,36); 
  fill(titleColor);
  text(heading,width/2,topMargin/2);     //Draw graph title.
  textAlign(RIGHT,BOTTOM);
  textFont(font,24);
  fill(200);
  text(credit,width-25,height-15);      //Draw credits.
}

//------------------------------------------------------------------------------
// Look for the values in "settings.txt" and set the variables accordingly.
//------------------------------------------------------------------------------
void  FillParams(){
  String splitLine[];
//-------- If "settings.txt" doesn't exist, create it.-------------
  if (loadStrings("settings.txt")== null){
    saveStrings("settings.txt", lines);         //each string is a line.
  } 
  else{  //Reading "settings.txt" and update variables:
    lines = loadStrings("settings.txt");        //lines is a string array
    splitLine = split(lines[0], ':');           //split line[0].
    comPortName= splitLine[1];                  //the substring after '='
    splitLine = split(lines[1], ':');           //split line[1].
    Gain= Float.parseFloat(splitLine[1]);       //the substring after '='
  }  

//---------- Show the content of "settings.txt" in the the console -------------
  println("there are " + lines.length + " lines in \"settings.tx\" file");
  for (int i=0; i < lines.length; i++) {
      println(lines[i]);                        //Send to console.
  }
      
  saveStrings("settings.txt", lines);           //Save the settings. 
}

//------------------------------------------------------------------------------
//Try to open the port specified in "settings.txt". 
//------------------------------------------------------------------------------
void PortManager(){
  
//------------- List the available COM ports in this system --------------------
  String[] portlist = Serial.list();  //Create a list of available ports.
  println("There are " + portlist.length + " COM ports:");
  println(portlist);
  
//----------- If COM port in "settings.txt" is available, open it  -------------
  for (int i=0; i < portlist.length; i++) {
      if(comPortName.equals(portlist[i]) == true){
          myPort = new Serial(this, portlist[i], 115200); //open serial port.       
          COMOPENED = true;
          println(portlist[i]+" opened");
      }
  }

//-------- Procedure when COM port is not available --------------------
  if(!COMOPENED){
      println(comPortName + " is not available");    //Anounce the problem
//      SelComPort();         //Procedure to select another port...
  }
}

 

An example of how to use the sensor:  Measure the position of a floating ball.

20140417_120633

Another  possible application, a laser ranger:

laser-ranger-concept

Working to increase the frames per second (FPS)…

Will be continued…

(in twitter you can follow my progress before it be posted here ): @arduining

 



Meduino NANO a versatile Arduino NANO clone

$
0
0

Two years ago I found the MEDUINO in Ebay (5 pieces for $44.95 including shipping).

Ebay_Meduino

Since then I have used them in several projects with good results.

For less than $10, you have an Arduino NANO compatible device with selectable working voltage (3.3V or 5V), additionally, you can use it as a USB-Serial adapter (FTDI chip) to interface or monitor other serial devices.

ADXL335_Meduino_NANOr

Meduino 3.3V capturing data from the ADXL335 accelerometer.

Meduino_photosensor

Meduino 5V transmiting light intensity from the Single Pixel Camera to Processing.

electric-imp-meduino-serial

Meduino 3.3V as a USB-Serial adapter to check MODBUS protocol with the electric imp.

Meduino-ESP8266-serial

Meduino 3.3V as power source and USB serial adapter for the ESP8266 Wi-Fi module.

The pin arrangement is like the Arduino NANO but with the Mini-USB connector on the opposite side. The PCB of the Meduino is also slightly larger.

Nano_Vs_Meduino

Meduino NANO and Arduino NANO pin assignment

The selectable Vcc (3.3/5V) is great to interface with different sensors and hardware.

ATmega328 overclocked:

One thing to consider for “serious” applications is the crystal frequency at 3.3V.

Meduino_Outlaw_d

The ATMega328 datasheet shows a Safe Operating Area, the maximum recommended frequency for 3.3V operation is 13.3 MHz.

The Meduino NANO with 3.3V at 16MHz is out of the recommended frequency but for experimenting purposes at room temperature, is a very handy and low cost Arduino.


Making ESP8266 breadboard friendly

$
0
0

Just receive some samples of the ESP-01 board. My first thought was how to use it with a breadboard?.

Doing some Web research found several custom adapters and DIY ideas.

After some brainstorming and a couple of coffees find out a simple procedure to have the ESP8266 nicely plugged in my breadboard.

The solution implies to cut four pins and solder a four pin 0.1 right-angle male header.

IMG_20141231_181709

The adhesive silicone dot helps to plug the module leveled.

 


 

 

The following images explain  themselves:

ESP8266-breadboard-friendly

IMG_20141231_181832

 


 

Ready for IoT fun projects…

ESP8266-Meduino-NANO


 

Sending random values of temperature and humidity to ThingSpeak:

ESP8266-Meduino-Thingspeak



 


Mini Client with the Arduino TRINKET and the ESP8266

$
0
0

ending the temperature to a ThingSpeak channel using the TMP35 sensor.

This is a small and low cost implementation of IoT (Internet of Things, possibly one of the next technological revolutions). Mini-Client-Trinket-ThingSpeak The ESP8266 can be used alone thanks to the apparition of several environments like LUA, C, Micro Python etc.. In this case I wanted to keep the solution in the Arduino environment to take advantage of many ready-to-use libraries and examples. Then I realized, due the reduced space in the Trinket (5.310Kb for code), the usability of such libraries it’s not so simple. Programming the ATtiny85 with an ISP programmer will permit the use of the full 8K programming memory. Anyway was a fun project, is great to see the small ATtiny85 acting as a Web Client. Let’s make the Trinket do the job using just the Arduino IDE.


Power considerations: The ESP8266 is power hungry when is communicating with a Wi-Fi spot. It can reach 215mA in Transmit Mode. The 3.3Vregulator in the Trinket only supply 150mA max. Then we need to use another 3.3V power source. The L4931 (250 mA) is working at first. A 470 uF capacitors is needed at the output.


Wiring diagram: (….. on the works)


Making the ESP8266 breadboard friendly:  To modify the ESP8266 we need a 0.1″ 4-pin right-angle male header. The procedure is very simple:ESP8266-breadboard-09 First cut (remove) the row of pines closer to the board border. Then, using a breadboard as guide and support, sold the right-angle header. Use enough solder to obtain a good mechanical resistance.     More images in this post: http://arduining.com/2015/01/02/making-esp8266-breadboard-frienly/


Mini breadboard wiring:

MiniClient_wiring

Wire color identification:

Black: ground.

Red: +5V.

Orange: 3.3V from the L4931 regulator.

Yellow: Trinket RX data (ESP8266 TX).

Purple: Trinket TX data (ESP8266 RX).

Blue: ESP8266 reset.

Green: Trinket analog input (TMP36 Vout).


Final assembly:

MiniClient_assembled

Everything in it’s place… let’s coding…


Temperature Sensor TMP35: TMP35_chart


The Trinket Sketch: At first, just ported the code from a working example made with the Meduino NANO and the DHT22 temperature sensor, finding out that the code size will be a problem. open-style-packaging-2


Several changes were implemented to reduce the code size: Changing to the TMP35 temperature sensor because is easier to read (don’t need a library ). Avoiding the use of string manipulation functions. Avoiding the use of floating math operations. (Only integer math was used). Integrating CR and LF at the end of the strings and using print() function instead of println(). Many other changes until the compiler of the Arduino IDE announced:

Binary sketch size: 4,748 bytes (of a 5,310 byte maximum)


The Sketch:

/*ESP8266_Trinket_01.ino Arduining.com (29 APR 2015)
Sending temperature data to ThingSpeak.
Hardware:
 -Adafruit's Arduino Trinket (3.3V)
 -ESP8266(ESP-01)
 -Temperature sensor TMP35

Data update rate set by the SPERIOD value.
Using SoftwareSerial at 9600 bauds.
String and math functions avoided.
The temperature is not calibrated.
  -ATtiny85 internal reference differs a little from 1.1V
  -The TMP35 is affected by radio frequencies.

Sketch uses 4,748 bytes (89%) of program storage space. Maximum is 5,310 bytes.
-----------------------------------------------------------------------------*/

#include <SoftwareSerial.h> 

//Network parameters and server IP address:
#define mySSID    "XXXXXXXXX"           //WiFi network ID.
#define myPASS    "XXXXXXXXX"           //Password.
#define serverIP  "184.106.153.149"     //IP of ThingSpeak.com
#define ChannKEY  "XXXXXXXXXXXXXXXX"    //ThingSpeak channel key.

#define updField  "1"                   //Updating Field( 1,2,3,4,5...)
#define SPERIOD   30000                 //Sampling period (milliseconds).
#define MAXFAILS  10                    //Number of fails to RESET the ESP8266.

//Concatenating the string messages:
#define mode_MSG  "AT+CWMODE=3\r\n"       //Dual mode (Station and Access Point).
#define join_MSG  "AT+CWJAP=\"" mySSID "\",\"" myPASS "\"\r\n"      //set data to join the AP.
#define conn_MSG  "AT+CIPSTART=\"TCP\",\"" serverIP "\",80\r\n"     //TCP, ThingSpeak, port 80.
#define send_MSG  "AT+CIPSEND=46\r\n"     //Send data, size=46 (4 bytes for the value)
#define upda_MSG  "GET /update?key=" ChannKEY "&field" updField "=" //Updating Field data.
#define clos_MSG  "AT+CIPCLOSE\r\n"       //Close TCP connection.


//Trinket pins assignament:
#define RXDATA    1      // SoftwareSerial receive pin (RED LED connected).
#define TXDATA    0      // SoftwareSerial transmit pin.
#define HRESET    3      // Pin to hardware Reset the ESP8266
#define ANATEMP   1      // Analog channel 1 for temperature measurement.

int i,j;
int fails=100;           // set failures>MAXFAILS to generate initial RESET.
unsigned int temp;       // Use positive range values (0-32768)
String tempVal="00.0";   // Four characters (fixed format number).

SoftwareSerial ESPSerial(RXDATA, TXDATA);   // Creates SoftwareSerial channel.

//====================== Setup ================================================
void setup(){
  
  analogReference(INTERNAL);        //Use the 1.1V internal reference.
  pinMode(HRESET,OUTPUT);           //hardware reset for the ESP8266.
  ESPSerial.begin(9600);
  initESP();                        // ESP8266 init.

}   //END of setup.

//====================== loop =================================================
void loop(){

  while((millis() % SPERIOD)>10){};   //Wait for the next multiple of SPERIOD.

  while(ESPSerial.read()!= -1){};     //Wait until no serial data available.

//------------- Here is the temperature reading for the TMP35 ------------------
/*-------------------------------------------------------------------
    For compactness of the code, integer math is used:
    TheTMP35 has 10 mV/°C scale factor:Temp in °C = (Vout in mV)/10 
    With Vref=1.1V the range is: 0°C to +60°C, (0.1 degree resolution)
    AnalogRead value (559) => 60 degree.
    32768/1024= 32 (maximum multiplier to keep the integer positive).
    Multiplier and divider factors are: 29/27= 1.0740 close to 1100/1024.
 --------------------------------------------------------------------*/
  temp= (analogRead(ANATEMP)* 29)/27;  //value in millivolts (1.1V internal ref.)

//------ formating the integer temp to a 4 character string ---------  
  tempVal[0]= '0'+(temp/100);
  tempVal[1]= '0'+(temp%100/10);
//  tempVal[2]= '.';   //decimal point already there.
  tempVal[3]= '0'+(temp%10);

  updateValue();
  if (fails > MAXFAILS) initESP();   //Reset and init ESP8266 after some fails.

}   // END of loop.

/*-----------------------------------------------------------------------------
Function updateValue() 
-----------------------------------------------------------------------------*/
void updateValue(){
  ESPSerial.print(conn_MSG);        //Open TCP connection with ThingSpeak.
  if(waitChar('K',10000)){          //Wait for 'K' of "OK".
    delay(250);                     //Delay to receive the message "Linked"
    ESPSerial.print(send_MSG);      //Send message AT+CIPSEND= and size.
    if(waitChar('>',10000)){        //Wait for '>'.
      ESPSerial.print(upda_MSG);    //Update Field value.
//      tempVal= "13.4";
      ESPSerial.print(tempVal);
//      ESPSerial.print("20.7");    // test value
      ESPSerial.print("\r\n");      //to replace println (less code).
      fails=0;                      // clear failure counter.
      return;                       // Unlink automatically....
    }
  }
  fails++;
  ESPSerial.print(clos_MSG);       //Close the TCP connection with ThingSpeak.  
}

/*-----------------------------------------------------------------------------
Function waitChar() 
-----------------------------------------------------------------------------*/
bool waitChar(char Wchar, int duration){
  for(i=duration;i>0;i--){
    delay(1);
    if(ESPSerial.read()== Wchar)return true;
  }
  return false;
}

/*-----------------------------------------------------------------------------
Function initESP() 
-----------------------------------------------------------------------------*/
void initESP(){
  while(1){
    if (fails > MAXFAILS){           //------Hardware reset for ESP8266.
      digitalWrite(HRESET,LOW);
      delay(100);
      digitalWrite(HRESET,HIGH);
      delay(5000);
      fails=0;
    }

    ESPSerial.print("AT\r\n");       //"\r\n" to replace println  (less code)
    delay(1000);
    if(waitChar('K',1000)){          //Wait for 'K' of "OK".
      ESPSerial.print(mode_MSG);     //Set Station mode.
      delay(250); 
      ESPSerial.print(join_MSG);     //Set name and password of the AP.
      if(waitChar('K',10000))return; //Wait for 'K' of "OK" to exit setup
    }
    fails++;
  }

}


Mini Client part list :

Adafruit-Part-List

Pictures from the Adafruit Industries web page.

1.- USB cable – A/MiniB. (1)
2.- Hook-up Wire 22AWG Solid Core (assorted colors) .(1)
3.- Tiny breadboard 170 contacts. (1)
4.- Adafruit’s Trinket – Mini Microcontroller – 3.3V Logic. (1)
5.- 3.3V 250mA Linear Voltage Regulator – L4931-3.3 TO-92. (1)
6.- 10uF 25V Electrolytic Capacitor. (1)
7.- 470uF 25V Electrolytic Capacitor. (1)
8.-TMP35 – Analog Temperature sensor. (1)
9.- ESP8266 WiFi Module. (1)

NOTE: A 0.1″ 4-pin right-angle male header is recommended to adapt the ESP8266 to the breadboard.


This Post Is Under Construction…

28 APR 2015 : New wiring,  Sketch posted.

… More info when requested and (or) available.

Thanks for reading.



Arduino Pro Trinket Pinout Diagram

$
0
0

Here is my quick reference to wire the Adafruit’s Pro Trinket.

Following the color sheme of the previous published Trinket pinout diagram.

http://arduining.com/2014/01/30/arduino-trinket-pin-diagram/

Pro_Trinket_pins_01

Pins A0-A5 can also be named as 14-19 for digital I/O ( digitalRead() and digitalWrite() ).


Very handy arduinos…

Four_Pro_trinkets

I’ll be posting some project with them…

My first approach was making a Christmas tree star, using Neopixels, last December…

B50LQdFIUAApVGn


Digital To Analog with Tiva C Launchpad and Energía

$
0
0

TIVA_C_and_energia2



There are nice Energía diagrams for this LaunchPad in the Web.

Nevertheless, to become familiar with the board functionality and pin layout (and because enjoy drawing) decided to make a diagram. Tiva C Launchpad Pinout Diagram :

Tiva_C_Launchpad_Pinout_001b

Since my first contact with Arduino always wanted to generate waveforms and see them in an oscilloscope. Almost three years ago made some projects with the MSP430 LaunchPad, can be seen at the SeuPay’s YouTube channel. Then also did some test with the Stellaris LaunchPad.

After more than a year with a couple of unboxed Tiva C LaunchPads, decided to try some waveforms generation with the inexpensive 32 bit, 80 MHz ARM platform. Using Energía, began some experiments with the Tiva C :

-Generating waves with the MCP4725, I2C 12-Bits DAC .

-Generating waves with the AD7801 Parallel 8-Bit DAC.

Direct Port Manipulation was used to reach higher data updates (samples/second).



 

Tiva C Launchpad and MCP4725

The first experiment generates wave shapes using an external DAC (Digital-To-Analog Converter).

The first choice was to use the MCP4725 from Adafruit’s (SparkFun also has a version with different address).

TIVA_C_MCP4725_wiring

The following sketch fills an array with the values of a sine wave and feeds the  DAC continuously with those values.

The “Fast Mode Write Command” of the MCP4725 is used.


/*MCP4725_Sin_01.ino   Arduining 17 APR 2015

-Energia Sketch to be used with Tiva C Launchpad and the Adafruit's MCP4725.
-I2C Fast Mode Write Command is used.
-120 samples are producing a 3.62Hz sine wave  => 434 samples/second.

Based in the code at:
http://electronics.stackexchange.com/questions/29457/how-to-make-arduino-do-high-speed-i2c
 
*/

#include 
#include 

//The MCP4725 from Adafruit:
//  I2C address is 0x62 ( by default A0 has a 10k pull-down resistor ).
//  I2C address is 0x63 if A0 is connected to VCC. 
#define MCP4725_ADDR 0x62           //I2c address..

int ch[ 360 ] , cl[ 360 ];          //Arrays to load the sine wave.

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

  Wire.begin();           // SCL(3) and SDA(3) by default in Tiva C.
  Wire.setModule(0);      // Changing to SCL(0)and SDA(0),(PB_2 and PB_3). 

  analogWrite(GREEN_LED,25);        //led 10% on.
  
// Create a sine table of 360 points:
  for ( int i = 0; i <= 360; i++ ) {
    int c = sin( i * 3.141592 / 180 ) * 2047 + 2048;
    ch[ i ] = int( c / 256 );      // the 4 most significant bits.
    cl[ i ] = c - ch[ i ] * 256;   // the 8 least significant bits.
  }
}

//------------------------------------------------------------------------
void loop() {
  for ( int i = 0; i < 360; i=i+3 ) {     //Only 120 points are used.
    Wire.beginTransmission(MCP4725_ADDR);
    //Fast Mode Write Command.
    Wire.write( ch[ i ] );        // the 4 most significant bits.
    Wire.write( cl[ i ] );        // the 8 least significant bits.
    Wire.endTransmission();
  }
}

This is the final result.

TivaC_MCP4725_01

The DSO Nano is very handy because fits anywhere close to my desktop computer and

has become an excellent and inexpensive monitor for debugging.

DSO Nano screen capture of a  simulated ECG wave (using the same hardware):

AD7801_ECGsmall_2


 

Working with C and Direct Registers (and Ports) Manipulation

Thanks to the page: http://users.ece.utexas.edu/~valvano/Volume1/E-Book/

Where the professor Valvano, from University of Texas at Austin, teach how to Develop Embedded Systems with the ARM M 4 Processor (Tiva C LaunchPad).

The chapters are mainly designed to work in C but, with some adjusts, the Energía environment does pretty good.

To enable Direct Register Manipulation we need to include in Energía the hardware register definitions.

Just write at the beginning of your code:

#include

This file is located in: C:\energia-0101E0015\hardware\lm4f\cores\lm4f\inc

I just made a copy and put it in: C:\energia-0101E0015\hardware\lm4f\libraries\tm4c123gh6pm

Notice that the file was copied inside a folder created with the same name.

(Surely there is a path to be included in Enegía to do this in a more elegant way).

Now you can use the Valvano’s examples in the Energía IDE, just remember to split the code appearing inside the main() function in two parts:

  – The configuration code goes inside the setup() function of Energía.

  – And the code running continuously is located inside the loop() function of Energía.

Is also possible to include Assembly code in Energía, but it needs another post.


 

Wiring the AD7801 8-Bits Parallel Digital to Analog Converter

A parallel DAC with 8 Bits is chosen to make the data transfer very fast.

Found the AD7801  at Mouser, the problem: (No DIP Package).

OK, let’s do some SMT work. With the DAC ordered and a  20 contact SOIC-to-DIP adapter.

…some SMT manual soldering…Breadboard-adapter-AD7801_02

A wiring diagram to connect the AD7801 to the Tiva C LaunchPad:

Tiva_C_AD7801_wiring

The AD7801, once soldered and wired, is very easy to operate. Simply put a new data in the PORTB and toggle PORTA bit 2 to produce a low pulse in the WR signal.

Did a A Quick-Ref of the chip:

QuickRef-AD7801

Then I had to study  Valvano’s code to understand how to deal with the Direct Register (and Ports) Manipulation.

First began to do the I/O Ports setup using the Direct Register manipulation, this part is not necessary, you can use Arduino code in Energía to do it. But was a good opportunity to learn  some details of the the ARM  Cortex M 4.

Finally, the code used to generate the fast data transfer between Tiva C launchpad and the AD7801:


/*AD7801_FastDAC.ino  Arduining.com 18 APR 2015

Testing the Tiva C LaunchPad and the AD7801 (Parallel Input 8-Bit DAC).
Using the PORTB to write the 8-Bit data.
Using PORTA bit 2 for the write signal (WR).

Results:
6 kHz    POINTS=256   ==>  1,536 Mega-samples/sec.
96 kHz   POINTS=16    ==>  1,536 Mega-samples/sec.
Note: faster if offset is a char.( 1,9 Mega-samples/sec.)
-----------------------------------------------------------------------------*/

#include     // TM4C123GE6PM Register Definitions.
#include             // To calculate the sine table.

// bits 7-0 of port B address (Data).
#define ldata     (*((volatile unsigned long *)0x400053FC))
// bit 2 of port A address (WR signal).
#define wrsignal  (*((volatile unsigned long *)0x40004010))

#define POINTS    256    // Wave points.(256 max. to keep offset as char type)
#define PEAKVAL   128    // Wave Amplitud (128 max, inside 8-Bits range)
#define OFFSET    128    // Center of the wave (128 for full 8-Bits span).

int sintable[POINTS];    // Array to load the sin table data.
int offset=0;           // index to point the data inside sintable[].

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

  PortB_Init();
  PortA_Init();

  // Fill the sin table with POINTS samples:
  for ( int i = 0; i <= POINTS; i++ ) {
    sintable[i] = sin( i * 3.141592 * 2 / POINTS ) * (PEAKVAL-1) + OFFSET ;
  }

}

void loop(){
    //Write data to the AD7801

    ldata= sintable[offset];        // Load value in the port B.
    wrsignal= 0;                    // WR signal to low.
    wrsignal= 4;                    // WR signal to high
    offset++;
    if((POINTS-offset)<=0)offset=0; // Keep offset in range.

  //  delayMicroseconds(2);           // To experiment different frequencies.
}

/*------------------------------------------------------------------------------
Subroutine to initialize port B all pins output.
Port B is used to output the data.
------------------------------------------------------------------------------*/
void PortB_Init(void){
  volatile unsigned long delay;
  SYSCTL_RCGC2_R |= 0x02;          // 1) activate Port B clock
  delay = SYSCTL_RCGC2_R;          // allow time for clock to stabilize
                                   // 2) no need to unlock PB7-0
  GPIO_PORTB_AMSEL_R &= ~0xFF;     // 3) disable analog functionality on PB7-0
  GPIO_PORTB_PCTL_R = 0x00000000;  // 4) configure PB7-0 as GPIO
  GPIO_PORTB_DIR_R |= 0xFF;        // 5) set PB7-0 as outputs
  GPIO_PORTB_AFSEL_R &= ~0xFF;     // 6) disable alt funct on PB7-0
  GPIO_PORTB_DR8R_R |= 0xFF;       // enable 8 mA drive on PB7-0
  GPIO_PORTB_DEN_R |= 0xFF;        // 7) enable digital I/O on PB7-0
}  

/*------------------------------------------------------------------------------
Subroutine to initialize port A pin 2 as output.
PA2 is used to drive the WR signal of the DAC.
------------------------------------------------------------------------------*/
void PortA_Init(void){
  volatile unsigned long delay;
  SYSCTL_RCGC2_R |= 0x01;           // 1) activate clock for Port A
  delay = SYSCTL_RCGC2_R;           // allow time for clock to start
                                    // 2) no need to unlock PA2 
  GPIO_PORTA_PCTL_R &= ~0x00000F00; // 3) regular GPIO 
  GPIO_PORTA_AMSEL_R &= ~0x04;      // 4) disable analog function on PA2 
  GPIO_PORTA_DIR_R |= 0x04;         // 5) set direction to output 
  GPIO_PORTA_AFSEL_R &= ~0x04;      // 6) regular port function 
  GPIO_PORTA_DEN_R |= 0x04;         // 7) enable digital port PA2
}
//End of code.


The complete assembly:

AD7801_FastSin_r

Two screenshots, thanks to the DSO Nano’s image capture function:

 A 6  kHz sine wave using POINTS= 256

and  a 95 kHz sine wave with POINTS= 16 .

The transfer speed is 1.536.000 samples/second.

AD8701_Speed_Test_2


 

Next steps:

Now we have a Sine Wave Generator, but the microcontroller is busy with this simple task.

If we need to do additional tasks like:

  • Change the frequency and (or) the amplitude on the fly.
  • Show  those values in a display.
  • Receive commands or transmit parameters serially.

 We need to use interruptions…

Thanks for reading Arduining blog.



Arduino and Two Stepper Motors

$
0
0

 

Two_Steppers

This project consist in moving two stepper motors “simultaneously”.
Really there is a loop where both motors are moved “one step at a time” to reach their final position.
5 Volts steppers with external power source are used.

 

Here is the video in YouTube:

Here is the Sketch:

—————-

/*------------------------------------------------------
Two_Steppers.ino     Arduining.com  30 MAY 2015

Driving two steppers concurrently with the Arduino Nano.
stepperX follows potentiometer on analog input 0.
stepperY follows potentiometer on analog input 1.
A timeout is used to turn off coils and save energy in battery
operated applications.

Hardware:
Arduino NANO.
Drivers: ULN2003A
Stepper Motors: 28BYJ48, 5VDC, step angle 5.625 °
                Gear reduction 64:1
                No-load starting frequency:> = 500PPS (4 rpm)
                Coil resistance 60 Ohms.               
 -----------------------------------------------------*/

#include <Stepper.h>

#define  STEPSREV    4096    // 64(fullsteps) * 64 (reduction ratio)
#define  SPEED       4       // motor speed (RPM)

#define  COIL_1X     11
#define  COIL_2X     9
#define  COIL_3X     10
#define  COIL_4X     8

#define  COIL_1Y     7
#define  COIL_2Y     5
#define  COIL_3Y     6
#define  COIL_4Y     4

#define  POT_X       0
#define  POT_Y       1                
#define  TIMEOUT     1000    //Turns off after 1 sec of inactivity.
#define  NOISE       8       //inmunity in steps because analog noisy readings.

// create the instances of the stepper class.
Stepper stepperX(STEPSREV, COIL_1X, COIL_2X, COIL_3X, COIL_4X);
Stepper stepperY(STEPSREV, COIL_1Y, COIL_2Y, COIL_3Y, COIL_4Y);

int potValX,potValY;           // potentiometers analog readings
int Xpos,Ypos;                 // Actual steppers positions(0-4096)->(0-360°)
int newXpos, newYpos;          // New steppers positions
unsigned long stampX, stampY;  // last move time stamped.

//============== functions ====================================================

//Read the potentiometers and map the reading to mach 360 degrees.
void readPots(){
  potValX = analogRead(POT_X);          // read POT_X value (0-1023).
  potValY = analogRead(POT_Y);          // read POT_Y value (0-1023).
  newXpos= map(potValX,0,1023,0,2047);  // Map pot X range to one stepper turn.
  newYpos= map(potValY,0,1023,0,2047);  // Map pot Y range to the stepper turn.
}
 
//-----------------------------------------------------------------------------
// Aproach stepperX to the newX position.
void aproachX(int newX){
  int Xdir = Xpos<newX ? 1 : -1;
  stepperX.step(Xdir);        // move one step in the Xdir direction.
  Xpos += Xdir;               // update Xpos.
  stampX = millis();          // stamp actual time.
  }

//-----------------------------------------------------------------------------
// Aproach stepperY to the newY position.
void aproachY(int newY){
  int Ydir = Ypos<newY ? 1 : -1;
  stepperY.step(Ydir);        // move one step in the Ydir direction.
  Ypos += Ydir;               // update Ypos.
  stampY = millis();          // stamp actual time.
  }

//-----------------------------------------------------------------------------
//Check for inactivity and turn off the steppers coils to save battery.
void CheckTimeout(){
  if((millis() - stampX) > TIMEOUT){   //Turn Off StepperX coils.
    digitalWrite(COIL_1X, LOW);
    digitalWrite(COIL_2X, LOW);
    digitalWrite(COIL_3X, LOW);
    digitalWrite(COIL_4X, LOW);
  }
  if((millis() - stampY) > TIMEOUT){   //Turn Off StepperY coils.
    digitalWrite(COIL_1Y, LOW);
    digitalWrite(COIL_2Y, LOW);
    digitalWrite(COIL_3Y, LOW);
    digitalWrite(COIL_4Y, LOW);
  }    
}


//=================== setup ===================================================
void setup(){
  stepperX.setSpeed(SPEED);  // set the X motor speed.
  stepperY.setSpeed(SPEED);  // set the Y motor speed.
  readPots();
  Xpos = newXpos;
  Ypos = newYpos;
}

//================= main loop =================================================
void loop(){
  readPots();
//if diference is greater than NOISE move steppers.
  if(abs(newXpos - Xpos)> NOISE) aproachX(newXpos);
  if(abs(newYpos - Ypos)> NOISE) aproachY(newYpos);

  CheckTimeout();   //check for inactivity.

}

 

—————-

 

 

 

 

 


Interrupts with the TRINKET analog comparator

$
0
0

Here I’m sharing a working example using the analog comparator of the Adafruit’s  TRINKET (ATtiny85).

Trinket_ISR

 

/*Trinket_comp_ISR.ino  Arduining.com 12 JUL 2015
  Sketch to test interrupts fron the analog comparator.
  2.5 Volt in ANI0 (voltage divider).
  Potentiometer input in ANI1  An interrupt is generated in every change of the comparator output (toggle).
  The interrupt set the flag  "triggered".
  The main loop program checks for the flag, if the flag is set, test the output value  of the comparator
  and modify the state of the LED according.*/

#define LED 4 

volatile boolean triggered=false;

//------------ Analog Comparator Interrupt Routine ----------------------------
ISR(ANA_COMP_vect){  
  triggered = true;
}
  
//-----------------------------------------------------------------------------
void setup(){
 pinMode(LED,OUTPUT);
  ADCSRB &= ~(1<<ACME);             //Set AIN1 as the negative input (Potentiometer).
  DIDR0 |= (1<<AIN1D)|(1<<AIN0D);   // disable digital inputs.
  
//ACSR – Analog Comparator Control and Status Register   
  ACSR = B00001000; // comparator interrupt enabled and tripped on toggle. (compare with AN1)
      //  ||||||||_ ACIS0 ACIS1, ACIS0: Analog Comparator Interrupt Mode Select
      //  |||||||__ ACIS1 10= falling edge; 11= raising edge; 00= toggle.
      //  ||||||___ ACIC  Reserved Bit
      //  |||||____ ACIE  Interrupt Enable
      //  ||||_____ ACI   Analog Comparator Interrupt Flag (R/W), write 1 to clear it.
      //  |||______ ACO   Analog Comparator Output (read only)
      //  ||_______ ACBG  1= Bandgap Select (1.1V); 0= compare with AIN0 (pin 6)
      //  |________ ACD   Analog Comparator Disable


  digitalWrite(LED, HIGH);//LED on for 100 milliseconds.
  delay(100);
  //Put the LED status as the analog comparator output (inverted)
  if(ACSR & (1<<ACO))digitalWrite(LED, LOW);
  else digitalWrite(LED, HIGH);
}

//-----------------------------------------------------------------------------
void loop(){
  if(triggered){
    if(ACSR & (1<<ACO))digitalWrite(LED, LOW);
    else digitalWrite(LED, HIGH);
    triggered= false;
    //while(1){}
  }
}




NodeMCU ESP-12 Development Kit V1.0

$
0
0

Here is my Pinout Diagram of this wonderful board for IoT development:

NodeMcuDevkit_v1.0_io

With added circuitry to manage the RESET and FLASH from the USB Serial Port, this board is  great for development.

After some LUA scripts and trying the Arduino IDE with it…  This Board is awesome!

NodeMcu_orange

I’ll continue experimenting with this one for a while…


NodeMCU Breathing LED with Arduino IDE

$
0
0

Breathing_LED

The first sketch used to test an Arduino compatible board is Blink.
After run Blink in my new NodeMCU Development Kit,
Started experiments with the WiFi connection:
-Mini servers to control leds, servos, etc..
-Send light intensity and temperature to ThingSpeak, Xively, Plotly etc..
-Serial data bridges
-etc.

The blue led in the board was used to signal the execution of a particular procedure.
Because the GPIO16 (DO) limitation to use the analogWrite() and looking to see my LED doing something else…

Inspired by the Apple’s “breathing” pattern used for the sleep indicator.
Here is the code to generate a “breathing LED”.

NOTE:
The Arduino code runs inside a multitasking application, the ESP8266 is running at the same time TCP and WiFi stacks.
The sketch can breake the multitasking execution if your code runs in a blocking section.
The delayMicroseconds() is one of those blocking functions, delay(0)  was used to prevent watchdog reset inside the PWM loops.

/*LED_Breathing.ino Arduining.com  20 AUG 2015
Using NodeMCU Development Kit V1.0
Going beyond Blink sketch to see the blue LED breathing.
A PWM modulation is made in software because GPIO16 can't
be used with analogWrite().
*/

#define LED     D0        // Led in NodeMCU at pin GPIO16 (D0).
 
#define BRIGHT    350     //max led intensity (1-500)
#define INHALE    1250    //Inhalation time in milliseconds.
#define PULSE     INHALE*1000/BRIGHT
#define REST      1000    //Rest Between Inhalations.

//----- Setup function. ------------------------
void setup() {                
  pinMode(LED, OUTPUT);   // LED pin as output.    
}

//----- Loop routine. --------------------------
void loop() {
  //ramp increasing intensity, Inhalation: 
  for (int i=1;i<BRIGHT;i++){
    digitalWrite(LED, LOW);          // turn the LED on.
    delayMicroseconds(i*10);         // wait
    digitalWrite(LED, HIGH);         // turn the LED off.
    delayMicroseconds(PULSE-i*10);   // wait
    delay(0);                        //to prevent watchdog firing.
  }
  //ramp decreasing intensity, Exhalation (half time):
  for (int i=BRIGHT-1;i>0;i--){
    digitalWrite(LED, LOW);          // turn the LED on.
    delayMicroseconds(i*10);          // wait
    digitalWrite(LED, HIGH);         // turn the LED off.
    delayMicroseconds(PULSE-i*10);  // wait
    i--;
    delay(0);                        //to prevent watchdog firing.
  }
  delay(REST);                       //take a rest...
}


ESP-201 an ESP8266 breadboard friend

$
0
0

To plug the ESP-201 in the breadboard is necessary to remove the 4 pin connector from the botton of the board and install it in the component side.

 

ESP-201_presenter

 

A quick pinout reference to start the wiring:

ESP-201_pinout

Note: GPIO9 and GPIO10 are connected to the FLASH memory (may be unusable). Here is a “surgery” procedure to use them: ESP-201 board modification

First experiment sending the analog value from A0 to ThingSpeak:

ESP-201_A0

 

Experimenting with different antennas:

ESP-201_Antenna_tests

Best results with the external antenna (the metal one):

ESP-201_A0_ThingSpeak

 

 

Experimenting with Deep Sleep:

In progress….SEP-201_DS_Wiring

Boot Modes


Battery Life of an ESP8266 design

$
0
0

ESP-12_onBatt_01

The use of the relatively “new” and absolutely  “cheap” ESP8266 IC generates a rush in the apparition of new IoT  applications.

Lately I’m looking for devices that can run on batteries for months.

A device inside my mailbox twittering when the door was opened.

A moisture sensor reporting every hour from a spot in the garden, sending the data to ThingSpeak .

A tank level sensor reporting when low critical level is reached.

etc…

Working with Energía and the Texas Intrument’s Launchpads found the EnergyTrace tool.

How EnergyTrace measure power?
A software controlled DC-DC converter generates the target power supply (1.2 V-3.6 V).
The time density of the DC-DC converter charge pulses equals the energy consumption of the target microcontroller.
A built-in calibration circuit defines the energy equivalent for a single charge pulse.
The width of pulses remains constant. By counting  the charge pulses during a period of timed the average current is calculated.

BatteryLife

By removing the jumper of 3.3V to the development section and connecting my ESP8266 based device the EnergyTrace can be used to estimate the battery life.

MSP432_EnergyMonitor

 

My  approach for the battery  power is to use a LDO regulator with very low quiescent current and 3 AA alkaline batteries.

regulator4

To reduce power the power-on LED and the light sensor LDR were removed.

The RGB led and some other resistors were also removed.

ESP12_Sleep_3xAA_02

This post is in construction….

blogger-at-work


ATtiny104 Xplained NANO, experimenting.

$
0
0

Atmel launches  the ATtiny104 Xplained Nano evaluation kit, a nice way of introducing this $0.40 microcontroller.

ATtiny104_img

The small and low cost evaluation board includes an on-board programmer.

After received two boards from Digikey, started downloading the Atmel Studio.

ATTINY104_X.jpg

The Atmel Studio is a “BIG” tool and takes time for the installation, but after the waiting, everything went smooth.

I spent some time drawing the Pinout Diagram, it helps me to learn more about the mini development kit.

ATtiny104_IOe.jpg

In no time the ATtiny104 was reading the PUSH BUTTON and controlling the on board LED.

Attiny104_blinking.jpg

Next thing to do:  experimenting with the serial port.

The character ‘U’ is sent every 500 milliseconds if the BUTTON is pressed.

The working code  transmitting at 9600 bauds:


 

/* ATTINY104_Serial.c
*  Created: 3/24/2016 08:20:00 PM
*  Author : Ardunaut
* Program to test serial transmission.
* While the BUTTON is pressed:
* 'U' character is transmitted every 500 milliseconds.
* The LED blinks when a char transmitted.
* FOSC=1000000 :"After powering up the device or after a reset the system clock is automatically
* set to calibrated internal 8MHz oscillator, divided by 8" (Datasheet pag.32)
* Using C functions from: http://www.atmel.com/Images/Atmel-42505-8-bit-AVR-Microcontroller-ATtiny102-ATtiny104_Datasheet.pdf
* Note: Zeros ('0') were removed from the register names to make the code compatible.
                 __________
           VCC--|1       14|--GND (TPI CLK)
           PA0--|2       13|--PB3 (CDC TX) -->USART_Transmit()
(TPI DATA) PA1--|3       12|--PB2 (CDC RX) <--USART_Receive()
   (RESET) PA2--|4       11|--PB1 (BUTTON)
           PA3--|5       10|--PB0
           PA4--|6        9|--PA7
     (LED) PA5--|7        8|--PA6
                \__________/
        Atmel ATtiny104 Xplained Nano
  */

#include <avr/io.h>
#include <util/delay.h>

#define LED_PIN    (1 << PA5)
#define BUTTON_PIN (1 << PB1)
#define FOSC 1000000
#define BAUD 9600
#define MYUBRR FOSC/16/BAUD   //adding or subtracting 1 may be necessary.

void PORTS_init(void){  
  PUEB |= BUTTON_PIN;         // Enable Pull-Up function in PB1.
  PORTB |= BUTTON_PIN;        // Set Pull-Up for the Button.
  DDRA |= LED_PIN;            // Configure LED pin as Output.
}

void USART_Init( unsigned int ubrr)
{
  /*Set baud rate */
  UBRRH = (unsigned char)(ubrr>>8);
  UBRRL = (unsigned char)ubrr;
  /*Enable receiver and transmitter */
  UCSRB = (1<<RXEN)|(1<<TXEN);
  /* Set frame format: 8data, 2stop bit */
  UCSRC = (1<<USBS)|(3<<UCSZ0);
  _delay_ms(250);
  PORTA |= LED_PIN;         // Switch off the LED.
  }
    
void USART_Transmit( unsigned char data )
{
  /* Wait for empty transmit buffer */
  while ( !( UCSRA & (1<<UDRE)) );
  /* Put data into buffer, sends the data */
  UDR = data;
}

unsigned char USART_Receive( void )
{
  /* Wait for data to be received */
  while ( !(UCSRA & (1<<RXC)) );
  /* Get and return received data from buffer */
  return UDR;
}

void USART_Flush( void )
{
  unsigned char dummy;
  while ( UCSRA & (1<<RXC) ) dummy = UDR;
}

/*----------------------------------------------------------------------------------------------------------------------------------------------------------*/
void main( void ){
  PORTS_init();
  USART_Init(MYUBRR);
  
  while(1){
    while(PINB & BUTTON_PIN){}  // Wait until the Button is pressed.
    PORTA &= ~LED_PIN;          // Switch on the LED.
    USART_Transmit( 'U' );
//    USART_Transmit( 85 );
    _delay_ms(50);
    PORTA |= LED_PIN;           // Switch off the LED.
    _delay_ms(450);
  }
}

 

 

Some soldering to continue experimenting with the Xplained NANO in a breadboard.

ATtiny104_breadboard

ATtiny104_ready

Now, looking for an efficient code and low power solution to create an IoT node…

First, testing the hardware:

ATtiny104_RFcoms (1)


 

Transmitting at 300 bauds with the USART connected to the 433Mhz RF module:

ATtiny104_RF300


 

This is the code to transmit “HELLO” every second (while the button is pressed).

/* * ATTINY104_RF300.c
* -Using the USART for 300 bauds transmission with the RF Module (433Mhz).
* -Tree 0xAA bytes are sent as preamble of the message to balance the receptor.
* -While the BUTTON is pressed "HELLO" message is transmitted every second aprox.
* -Characters are separated 50 milliseconds (20 milliseconds of mark).
* -The LED is ON during the message is transmission.
* -FOSC= 1000000 : "After powering up the device or after a reset the system clock is automatically
*  set to calibrated internal 8MHz oscillator, divided by 8" (Datasheet pag.32)
* -Using C functions from: http://www.atmel.com/Images/Atmel-42505-8-bit-AVR-Microcontroller-ATtiny102-ATtiny104_Datasheet.pdf
* -Note: Zeros ('0') were removed from the register names to make the code compatible.
* -Created: 3/26/2016 07:25:00 PM
* -Author : Ardunaut
                 __________
           VCC--|1       14|--GND (TPI CLK)
           PA0--|2       13|--PB3 (CDC TX) -->USART_Transmit()
(TPI DATA) PA1--|3       12|--PB2 (CDC RX) <--USART_Receive()
   (RESET) PA2--|4       11|--PB1 (BUTTON)
           PA3--|5       10|--PB0
           PA4--|6        9|--PA7
     (LED) PA5--|7        8|--PA6
                \__________/
        Atmel ATtiny104 Xplained Nano 
*/

#include <avr/io.h>
#include <util/delay.h>

#define LED_PIN    (1 << PA5)
#define BUTTON_PIN (1 << PB1)
#define FOSC 1000000 // Clock Speed 
#define BAUD 300     
#define MYUBRR FOSC/16/BAUD-1

void PORTS_init(void){  
  PUEB |= BUTTON_PIN;         // Enable Pull-Up function in PB1.
  PORTB |= BUTTON_PIN;        // Set Pull-Up for the Button.
  DDRA |= LED_PIN;            // Configure LED pin as Output.
}

void USART_Init( unsigned int ubrr){
  //Set baud rate:
  UBRRH = (unsigned char)(ubrr>>8);
  UBRRL = (unsigned char)ubrr;
  //Enable receiver and transmitter:
  UCSRB = (1<<RXEN)|(1<<TXEN);
  // Set frame format: 8data, 2stop bit :
  UCSRC = (1<<USBS)|(3<<UCSZ0);
  _delay_ms(250);
  PORTA |= LED_PIN;         // Switch off the LED.
  }
    
void USART_Transmit( unsigned char data ){
  // Wait for empty transmit buffer:
  while ( !( UCSRA & (1<<UDRE)) );
  // Put data into buffer, sends the data:
  UDR = data;
}

unsigned char USART_Receive( void ){
  // Wait for data to be received:
  while ( !(UCSRA & (1<<RXC)) );
  // Get and return received data from buffer :
  return UDR;
}

void USART_Flush( void ){
  unsigned char dummy;
  while ( UCSRA & (1<<RXC) ) dummy = UDR;
}
/*----------------------------------------------------------------------------------------------------------------------------------------------------------*/
void main( void ){
  PORTS_init();
  USART_Init(MYUBRR);
  
  while(1){
    while(PINB & BUTTON_PIN){}  // Wait until the Button is pressed.
    PORTA &= ~LED_PIN;          // Switch on the LED.
    
    USART_Transmit( 0xAA );   // To balance the receptor.
    _delay_ms(50);
    USART_Transmit( 0xAA );   // To balance the receptor.
    _delay_ms(50);    
    USART_Transmit( 0xAA );   // To balance the receptor.
    _delay_ms(50);
    USART_Transmit( 'H' );
    _delay_ms(50);
    USART_Transmit( 'E' );
    _delay_ms(50);
    USART_Transmit( 'L' );
    _delay_ms(50);
    USART_Transmit( 'L' );
    _delay_ms(50);
    USART_Transmit( 'O' );    

    PORTA |= LED_PIN;         // Switch off the LED.
    _delay_ms(650);           // delay to complete one second.
  }
}

More experiments and learning …

blogger-at-work


ATtiny104 ADC and USART Example

$
0
0

This is a working example of the analog acquisition made with the ATTINY104.

ATtiny104_ADC_example2

 

ATtiny104 Xplained NANO and Atmel Studio 7 was used.


 

Here is the  C code:

 

/*ATtiny104_ADC_Serial.c
* Example of the DAC operation.
* A potentiometer is used to produce voltage variations at PA6 (ADC3),
* Analog value (upper 8 bits) is read and sent serially at 9600 bauds every 500 msecs.
* Created: 3/29/2016 10:30:00 PM
* Author : Ardunaut
                     ____________
               VCC--|1         14|--GND
  TPI CLK/ADC0 PA0--|2         13|--PB3 ADC7/CDC TX -->USART_Transmit()
 TPI DATA/ADC1 PA1--|3         12|--PB2 ADC6/CDC RX <--USART_Receive()
    (RESET)    PA2--|4         11|--PB1 ADC5/BUTTON
               PA3--|5         10|--PB0 ADC4
               PA4--|6          9|--PA7
      LED/ADC2 PA5--|7          8|--PA6 ADC3  <---- Potentiometer
                     \__________/
             Atmel ATtiny104 Xplained Nano
*/

#define F_CPU 1000000
#include <avr/io.h>
#include <util/delay.h>
#define LED_PIN    (1 << PA5)
#define BUTTON_PIN (1 << PB1)       // Not used in this example
#define BAUD 9600
#define MYUBRR F_CPU/16/BAUD        // +1, 0 or -1 to adjust the timming.

void PORTS_Init( void ){
  PUEB |= BUTTON_PIN;               // Enable Pull-Up function in PB1.
  PORTB |= BUTTON_PIN;              // Set Pull-Up for the Button.
  DDRA |= LED_PIN;                  // Configure LED pin as Output.
}

void USART_Init( unsigned int ubrr){  // Initialize USART
  UBRRH = (unsigned char)(ubrr>>8); // Set the baud rate
  UBRRL = (unsigned char)ubrr;
  UCSRB = (1<<RXEN)|(1<<TXEN);      // Enable Receiver and Transmitter
  UCSRC = (1<<USBS)|(3<<UCSZ0);     // Set Format: 8 data, 2 stop bit
}

void USART_Transmit( unsigned char data ){
  while ( !( UCSRA & (1<<UDRE)) );  // Wait for empty buffer.
  UDR = data;                       // Put data into buffer.
}

unsigned char USART_Receive( void ){
  while ( !(UCSRA & (1<<RXC)) );    // Wait for received data.
  return UDR;                       // Return received data.
}

void USART_Flush( void ){
  while ( UCSRA & (1<<RXC) ){};
}

void ADC_Init( void ){         // Initialize the ADC 

 //Set Voltage reference as VCC and select channel ADC3 (PA6).
  ADMUX =
            (0 << REFS1) |     // VCC as V. reference, bit 1
            (0 << REFS0) |     // VCC as V. reference, bit 0
            (0 << MUX2)  |     // use ADC3 (PA6), MUX bit 2
            (1 << MUX1)  |     // use ADC3 (PA6), MUX bit 1
            (1 << MUX0);       // use ADC3 (PA6), MUX bit 0
      
  //Set prescaler to 64 for MCU running at 8MHz (125 ksasmples/sec)
  ADCSRA =
            (1 << ADEN)  |     // Enable ADC 
            (1 << ADPS2) |     // Set prescaler=64 (125kHz), bit 2 
            (1 << ADPS1) |     // Set prescaler=64 (125kHz), bit 1 
            (0 << ADPS0);      // Set prescaler=64 (125kHz), bit 0 
      
  // ADLAR is set to 1 (Left-shift result, bits ADC9..ADC2 in ADCH)     
  ADCSRB =  
          (1 << ADLAR);        // Left Adjustment for ADC Result Readout 
}

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

int main( void ){
  PORTS_Init();
  USART_Init(MYUBRR);
  ADC_Init();
  uint8_t digit,data;
  
  while(1){
    ADCSRA |= (1 << ADSC);          // start ADC measurement
    while (ADCSRA & (1 << ADSC) );  // wait till conversion complete 
  
    PORTA &= ~LED_PIN;              // Switch on the LED.
    data= ADCH;
    digit= data/100;
    USART_Transmit( '0'+digit );    // Transmit hundreds
    digit= (data % 100)/10;
    USART_Transmit( '0'+digit );    // Transmit tens
    digit= data % 10;
    USART_Transmit( '0'+digit );    // Transmit units
    USART_Transmit( 13 );           // Transmit Car Return
    USART_Transmit( 10 );           // Transmit Line Feed    
    _delay_ms(50);
    PORTA |= LED_PIN;               // Switch off the LED.
    _delay_ms(450);                 // Delay before next data acquisition.
  }

}  // End of main.

 

 


ATtiny104 Xplained NANO Pinout Reference

$
0
0

My Quick Pinout Reference of the ATtiny104 Xplained NANO Development Kit:

ATtiny104_Pinout_03



Wiring TFT Display to Arduino NANO

$
0
0
 Wiring Diagram:

TFT_SD_NANO_DIM_wiring

A clean approach to attach the Display to Arduino NANO:

TFT_SD_NANO_DIM_jumpers

 All the components in place. SD Card adapter also is connected to the Arduino.

TFT_SD_NANO_DIM_assembled

Reading the analog input A0:

Test_001

Plotting the analog channel A0 using vertical lines:

Test_002

A small video to show the wiring while enjoying a Tchaikovsky’s  Waltz:

 

Testing my small library. 5×7 font in different sizes.

MicroLib_03_text

Testing drawRect() and fillRect() of the small library:

MicroLib_03_Rect_test

 Using the small library to show A0 value and his histogram:

MicroLib_A0_test_img

 

 

… this post is in progress… some code and examples…

 


Tiva C LaunchPad Base Plate, Easy Wiring

$
0
0

A week ago went back to to Tiva C launchPad, this time I am interested in to refresh some concepts and try examples of RTOS (Real Time Operating System). The use of a RTOS usually means several hardware peripherals (sensors, keypads, displays .. etc). A breadboard and many jumpers was filling my imagination.

 

Tiva_Clean_Wiring

I need a Base Plate to organize the wiring, also a way of use top and bottom connectors in the launchPad. This is the story of last two days…

First thing, I need to finish the assembly of a tablesaw from Grizzly (it was resting semi-assembled in the garage).

Grizzly_tableSaw.jpg

Note:This project will be done in a couple of hours using acrylic plastic  if you have access to a laser cutter, in my case I am fan of woodworking… (the laser will come some day…).

TivaC_BasePlate_4.jpg

A serie of images will explain the project…

TivaC_BasePlate_3

While dried, we need a pin reference for the bottom:

TivaC_Launchpad_Bottom_pin_ref

TivaC_bottom_01

Time to put all together…

TivaC_BasePlate_2

TivaC_BasePlate_1

Tiva_Clean_Wiring_3

Here is how looks the wiring of the TFT Display:

Tiva-Clear_Wiring_2

This is the wiring diagram of the ST7735 used:

TIVA_ST7735_Wiring_

… thanks for visiting.

 

 

 


Simple Graph With Arduino NANO and TFT Library

$
0
0

This is a simple plotting example to experiment with the TFT Library and the LCD Display with the ST7735 controller (128×160 pixels).

simple_graph_01_4

First, a clean wiring diagram to connect the Arduino NANO and the Display. The SD Card adapter was wired  (CS and MISO) but not used in this Sketch.

tft_sd_nano_dim_wiring

Then, a wiring plan to put them together in the breadboard:

tft_sd_nano_dim_jumpers

 

tft_sd_nano_dim_assembled


 

The Sketch:

 

/*TFT_Graph.ino      Arduining 7 AUG 2016

-Arduino NANO and ST7735 LCD Display 128×160
-using TFT library
-Brighness control in pin 6
-offset is used to adjust vertical position of the graph.
*/

#include <TFT.h>
#include <SPI.h>

//pin definitions:
#define CS          10
#define DC           9
#define RST          8
#define BKLIGHT      6              // Backlight control pin

#define BRIGHTNESS 204              // Backlight intensity (0-255)
#define RANGE      100              // Vertical size of the graph in pixels.
#define WIDTH      128              // Horizontal size of Display in pixels.
#define HEIGHT     160              // Vertical size of Display in pixels.
#define PERSIST    500              // persistence of the graph (milliseconds).

TFT TFTscreen = TFT(CS, DC, RST);

int value ;
int last_value;
int x_pos= 0;                       // cursor position
int offset= 40;                     // vertical graph displacement in pixels.

void setup(){
TFTscreen.begin();                // initialize the display
TFTscreen.setRotation(0);
TFTscreen.background(0,128,0);    // dark green background
TFTscreen.stroke(255,255,255);    // white stroke
analogWrite(BKLIGHT,BRIGHTNESS);  //Set brightness.
TFTscreen.setTextSize(1);
TFTscreen.text(“Arduining.com”,50,151);
drawFrame();
clearGraph();
}

void drawFrame(){
TFTscreen.stroke(255,255,255);      // white stroke
TFTscreen.fill( 255, 255, 255 );    // White fill
TFTscreen.rect(0, 0, WIDTH, 21);
TFTscreen.setTextSize(1);
TFTscreen.stroke(0,0,0);            // black text
TFTscreen.text(“Volts: 1.0V/Div”,2,2);  // Example text.
TFTscreen.text(“Time:  10mS/Div”,2,12); // Exanple text
}
void clearGraph(){
TFTscreen.stroke(127,127,127);      // grey for the border
TFTscreen.fill( 180, 0, 0 );        // dark Blue for the background
TFTscreen.rect(0, 22, 128, 128);
TFTscreen.line(65, 23, 65, 151);    // vertical line
TFTscreen.line(1, 85,127, 85);      // horizontal line
TFTscreen.stroke(0,255,255);        // yellow stroke for plotting.
}

void plotLine(int last,int actual){
if(x_pos==0)last= actual;                     // first value is a dot.
TFTscreen.line(x_pos-1, last, x_pos, actual); // draw line.
x_pos++;
if(x_pos > WIDTH){
x_pos=0;
delay(PERSIST);
clearGraph();
}
}

void loop(){
last_value= value;
value= analogRead(A0);
value= map(value,0,1023,149,23);
value -= offset;
if(value <= 23) value= 23;         //truncate off screen values.
plotLine(last_value ,value );
delay(10);
}

 


Thanks for visiting…


Arduino Sketch upload via Bluetooth

$
0
0

After a Smart Robot Kit assembly :

ROBOT_Assembly (1).jpg

Start looking for a way to upload Sketches to the Arduino  wirelessly.

After some Internet searching… decided to go deeper and understand how the HC-06 Bluetooth module works and how is the upload process.

In the HC-06, the STATUS signal indicates when a Bluetooth bind condition is established.

After look at the signal,  the first idea was to use an LM555 as a resettable monostable multivibrator… ok,  an 8 pin DIP IC and several passive components….

Then why no use an ATTINY85 to do the work?

Here is the proof of concept using an Adafruit’s TRINKET 3.3V.

blue_remoteprogramming


The TRIKET checks the behavior of the STATE signal to identify the bind condition and generates the RESET pulse.

bluetooth_hc-05_status

 

Test made with an Arduino NANO clone:

wireless_sketch_upload

Testing Arduino Duemilanove (same HC-06 configuration, 57600 bauds):

BT_RemoteProg.jpg


The Sketch used in the TRINKET:

/*Trinket_BlueReset.ino   Arduining 4 OCT 2016
 Using TRINKET to generate the RESET for Remote Arduino Programming.

 -HC-06 BlueTooth Module as Slave 115200 bauds (UNO, Optiboot loader)
 -HC-06 BlueTooth Module as Slave 57600 bauds (Duemilanove, NANO)
 -Using the STATUS pin of The HC-06 to identify a Binded condition.
 -The TRINKET LED (pin 1) show the Bluetooth condition:
          5 Hz Not Binded, 1 Hz Binded.

 -STATPIN is the STATUS signal from HC-06 (pin 24).
 -RESETPIN is the RESET signal to start the bootloader in the Arduino.
             |<--200mSeg-->|             |<120mSeg>|
              ______        ______        _______________________________
   STATPIN __|      |______|      |______|
           --------------  Not Binded ------------>|<----- Binded -------
            _______________________________________ _____________________
   RESETPIN                                        |


  -If no changes in STATPIN for 120 milliseconds a RESETPIN pulse is generated.

                           __,-----,__
                          |[]|_____|[]|<===LED
   [----- (4.3-16)V ----->|o         o|[---- +USB(+5V 500mA) ---->
   <-------- GND -------->|o         o|<PB0>-<0>-[0A>-<SDA>-[MOSI>  ==> RESETPIN
   USB-<4A]-[A4>-<4>-<PB4>|o TRINKET o|<PB1>-<1>-[1A>-------<MISO]-LED>
   USB------[A3>-<3>-<PB3>|o         o|<PB2>-<2>-<A1]-[SCL>-[SCK >  <== STATPIN
   [-------- RESET------->|o         o|+3.3V(150mA)Reg. from BAT->
                          |   [( )] __|
                           \_______/
                  Trinket (3.3V) Pinout Diagram  

 -----------------------------------------------------------------------------*/

#define LEDPIN     1               // LED PIN for signaling.
#define RESETPIN   0               // Attached to the RESET pin of the Arduino.
#define STATPIN    2               // Attached to the STATUS pin of the HC-06
volatile bool flag= false;
int pulseTimer= 120;               // Waiting time for pulses in STATPIN (mSeg)

/*------------------------------------------------------------------------------
  setup()
------------------------------------------------------------------------------*/
void setup(){
    GIMSK = 0b00100000;            // turns on pin change interrupts
//    PCMSK = 0b00010011;          // turn on interrupts on pins PB0, PB1, & PB4
    PCMSK = 0b00000100;            // turn on interrupts on pin 2 (PB2)
    sei();                         // enables interrupts
    
    pinMode(LEDPIN, OUTPUT);    
    pinMode(RESETPIN, OUTPUT);
    pinMode(STATPIN, INPUT_PULLUP);
    digitalWrite(RESETPIN, HIGH);  // Set RESET to High.  
}

/*------------------------------------------------------------------------------
  loop()
------------------------------------------------------------------------------*/
void loop(){
  delay(1);

	if(flag){
    pulseTimer=120;                // Reset waiting time for pulses in STATPIN.
    flag = false;
	}
  else pulseTimer--;
  
	if(pulseTimer == 0){
    //Here we can check for a '0' in the serial channel (57600 bauds).
	  digitalWrite(RESETPIN, LOW);   // Produce a RESET pulse of 1 millisecond.
    delay(1);
    digitalWrite(RESETPIN, HIGH);  // Return to High.
    
    while(!flag){
      digitalWrite(LEDPIN,LOW);
      delay(500);
      digitalWrite(LEDPIN,HIGH);
      delay(500);          
      }                            // Hold until next Binding.
	}

}

/*------------------------------------------------------------------------------
  Pin Change Interrupt of pin 2 (PB2).
------------------------------------------------------------------------------*/
ISR(PCINT0_vect){
    flag = true;                   // signals the change in pin 2.
    digitalWrite(LEDPIN,digitalRead(STATPIN));   //Signaling the HC-06 STATUS.
    sei();                         // enables interrupts
}


 

If the Arduino to be programmed works with 3.3V the wiring is simpler:

arduino3v3_remoteprogr

Now we can program the Arduino without the USB cable. Also we can control the robot remotely via Bluetooth, just remember to use  Serial.begin(57600) in your control program  ….

Any additional ideas will be appreciated,

Thanks for visiting this blog.


Using Bipolar Stepper Motors With Arduino and Easy Driver

$
0
0

Controlling the NEMA 17 MERCURY SM-42BYG011-25

UNO_EasyDriver_Wiring_02

Arduino Sketch highlighted using  http://hilite.me/ :

/*EasyDriver_Test.ino  Arduining.com  6 MAY 2012

Sketch used to test the EasyDriver board from Sparkfun.com
Used in the YouTube video (Jul 15, 2012): "Arduino EasyDriver and Stepper Motor "

During the test a movement of 360 degrees (full turn) was implemented.
The stepper turns right and left alternatively.

Hardware:
-EasyDriver v4.4
  MS1 and MS2 connected to ground to select Full-Step mode.

-Stepper Motor SM-42BYG011-25 features:
  • Step Angle (degrees) :1.8
  • 2 Phase
  • Rated Voltage : 12V
  • Rated Current : 0.33A
  
*/

#define DIR   2
#define STEP  3

void advance(int steps)
{
  if(steps>0)digitalWrite(DIR, LOW); // Set clockwise direction.
  else{
    digitalWrite(DIR, HIGH);         // Set counter-clockwise direction.
    steps=abs(steps);
  }
  for (int i = 0; i<steps; i++){     // Rotate n steps.
    digitalWrite(STEP, HIGH);
    delayMicroseconds(20);           // Minimum STEP Pulse Width 1.0uS
    digitalWrite(STEP, LOW);         // Step pulse (rising edge).
    delay(10);                       // Delay between steps
  }
} 

void setup()
{
  pinMode(DIR, OUTPUT);
  pinMode(STEP, OUTPUT);
}

void loop()
{
  delay(250);
  advance(200);
  delay(250);
  advance(-200);
}


Controlling the DOWONSOL-9181 Stepper

EasyDriver_Pot_01


Arduino Sketch highlighted using  http://hilite.me/ :

/*------------------------------------------------------
EasyDriver_Pot_01.ino  Arduining 31 MAY 2015

Stepper motors following a potentiometer on analog input 0.
A software low-pass filter is used to reduce the noise in the analog reading.

The ENABLE signal is used to shut-down the current and keep the motor cold.

Hardware:
-Arduino UNO
-EasyDriver v4.4
  MS1 and MS2 connected to GND. (single stepping)
-Stepper Motor DOWONSOL:
  Model: 9181
  Voltage: 12V
  Coils impedance: 70 Ohms. (measured)
  Motor Step angle: 18 degrees
  GearBox reduction: 36:1
  Output angle/step: 0.5 degree  (720 pulses/revolution)
-Stepper Motor MERCURY:
  Model: ST-PM35-15-11C
  Voltage: 12V
  Motor Step angle: 48 degrees
  Output angle/step: 7.5 degree  (48 pulses/revolution)

 -----------------------------------------------------*/
#define MS1   12
#define MS2   11
#define STEP  10
#define DIR   9
#define EN    8

#define POT   0
#define TURN  720      //number of steps per revolution (DOWONSOL)
//#define TURN  48      //number of steps per revolution (MERCURY)
int potVal,targetPos;
int lastPot=0;
int actualPos=0;

void pulse(){
    digitalWrite(STEP, HIGH);
    delayMicroseconds(20);         // Minimum STEP Pulse Width 1.0uS
    digitalWrite(STEP, LOW);       // Step pulse (rising edge).
} 

void setup()
{
  pinMode(DIR, OUTPUT);
  pinMode(STEP, OUTPUT);
  pinMode(MS1, OUTPUT);
  pinMode(MS2, OUTPUT);
  pinMode(EN, OUTPUT);
  
  digitalWrite(MS1, LOW);          // Full step selected
  digitalWrite(MS2, LOW);          // Full step selected
  digitalWrite(EN, HIGH);          // Disable the A3967 IC.
}

void loop()
{
  potVal = analogRead(POT);       // Potentiometer value range 0-1023
  potVal= potVal * 0.1 + lastPot * 0.9 ;  // Filtering to reduce noise.
  lastPot= potVal;
  targetPos= map(potVal,0,1023,0,TURN);   // Map pot range in the stepper range.
  if(abs(targetPos - actualPos)> 1){      //if diference is greater than 1 step.
      digitalWrite(EN, LOW);              // Enable the A3967 IC.
      if((targetPos - actualPos)> 0){
          digitalWrite(DIR, LOW);         // Set counter-clockwise direction.
          pulse();                        // move one step to the right.
          actualPos++;
          }
      else{
          digitalWrite(DIR, HIGH);        // Set counter-clockwise direction.
          pulse();                        // move one step to the right.
          actualPos--;
      }
  }
  delay(5);
  digitalWrite(EN, HIGH);                 // Disable the A3967 IC.
}

Youtube video:

https://www.youtube.com/watch?v=S5vF9NEeOhA




Viewing all 20 articles
Browse latest View live