NodeMCU Breathing LED with Arduino IDE

August 20, 2015 Leave a comment

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...
}

NodeMCU ESP-12 Development Kit V1.0

August 15, 2015 Leave a comment

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…

Interrupts with the TRINKET analog comparator

July 12, 2015 Leave a comment

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){}
  }
}


Arduino and Two Stepper Motors

May 30, 2015 4 comments

 

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.

}

 

—————-

 

 

 

 

 

Serial Commands to Arduino ( LED control )

May 4, 2015 2 comments

Serial_LED_control A small sketch to show how to implement a command menu using the Serial Monitor of the Arduino IDE. In this example the switch statement is used to identify the received command and execute the corresponding action.

— Command list: —

? -> Print this HELP

a -> LED On  “activate”

d -> LED Off “deactivate”

s -> LED     “status”


The SKETCH:

/*Serial_LED_02.ino  Arduining 4 May 2015
Controlling the LED in pin 13 with the Serial Monitor.
--- Command list: ---
? -> Print this HELP 
a -> LED On  "activate"
d -> LED Off "deactivate"
s -> LED     "status" 

Example using the switch statement.
*/
 
#define LED 13          // Pin 13 is connected to the LED
char rxChar= 0;         // RXcHAR holds the received command.

//=== function to print the command list:  ===========================
void printHelp(void){
  Serial.println("--- Command list: ---");
  Serial.println("? -> Print this HELP");  
  Serial.println("a -> LED On  \"activate\"");
  Serial.println("d -> LED Off \"deactivate\"");
  Serial.println("s -> LED     \"status\"");  
  }
  
//---------------- setup ---------------------------------------------
void setup(){
  Serial.begin(9600);   // Open serial port (9600 bauds).
  pinMode(LED, OUTPUT); // Sets pin 13 as OUTPUT.
  Serial.flush();       // Clear receive buffer.
  printHelp();          // Print the command list.
}

//--------------- loop ----------------------------------------------- 
void loop(){
  if (Serial.available() >0){          // Check receive buffer.
    rxChar = Serial.read();            // Save character received. 
    Serial.flush();                    // Clear receive buffer.
  
  switch (rxChar) {
    
    case 'a':
    case 'A':                          // If received 'a' or 'A':
	if (digitalRead(LED) == LOW){        // If LED is Off:
          digitalWrite(LED,HIGH);      // Turn On the LED.
          Serial.println("LED turned On");
	}
        else Serial.println("LED already On!");
        break;

    case 'd':
    case 'D':                          // If received 'd' or 'D':
	if (digitalRead(LED) == HIGH){       // If LED is On:
          digitalWrite(LED,LOW);       // Turn Off the LED.
          Serial.println("LED turned Off");
	}
        else Serial.println("LED already Off!");
        break;
        
    case 's':
    case 'S':                          // If received  's' or 'S':
	if (digitalRead(LED) == HIGH)        // Read LED status.
          Serial.println("LED status: On");
        else Serial.println("LED status: Off");
        break;
        
    case '?':                          // If received a ?:
        printHelp();                   // print the command list.
        break;
        
    default:                           
      Serial.print("'");
      Serial.print((char)rxChar);
      Serial.println("' is not a command!");
    }
  }
}
// End of the Sketch.

Digital To Analog with Tiva C Launchpad and Energía

April 17, 2015 Leave a comment

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 Pro Trinket Pinout Diagram

April 2, 2015 Leave a comment

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

Follow

Get every new post delivered to your Inbox.

Join 33 other followers