Archivo de la etiqueta: Variables

Programación Básica en Python

Introducción a Python

Python es un lenguaje interpretado, es decir, no requiere del proceso de escribir / compilar / volcar. Simplemente escribir la instrucción y listo el ordenador la “interpreta” o sea ejecuta sobre la marcha sin más complicación.

Python también es:

Esto hace que los lenguajes interpretados sean más fáciles de aprender porque nos parecen más naturales, y aunque el programa corre más lento que en los compilados, pero con la potencia actual o es tan importante.

Python no es un lenguaje diseñado para ser fácil comprometiendo su potencia. Muy al contrario la potencia y capacidad de cálculo que muestra suelen sorprender a la gente acostumbrada a otros lenguajes.

Para quienes vengáis de Arduino, C++ es un lenguaje compilado, esto significa que el compilador lee lo escrito en una primera pasada y después compila, es decir traduce a un lenguaje propio del micro de Arduino qué es lo que se vuelca y ejecuta la placa que usemos.

Hay dos versiones de Python 2 y 3, pero la versión 2 ya no tienes soporte desde el 1 de enero de 2020, aunque en Raspbian disponemos de las dos versiones. El inconveniente es que hay librerías que aún se mantienen en Python 2.

Para iniciar python se puede hacer desde consola:

  • python
  • python3

O usar el entorno gráfico con IDLE. IDLE significa Integrated DeveLopment Environment, o Integrated Development and Learning Environment.

Para instalarlo ejecutar: sudo apt-get install idle3

Dentro de la consola ya es posible ejecutar comandos.

Otra opción es usar el Thonny Python IDE incluido en Raspbian: https://thonny.org/

Práctica: Ejecutar los comandos:

  • 3.8 + 7
  • 2 * (3+5) / 4
  • “Hola.”
  • x=3
  • H=”Buenos dias”
  • print(x)
  • print(h)
  • print(H)
  • print(x,H)
  • 123 ** 1234

Python puede con grandes números mientras le quede memoria RAM, pero tu Raspberry puede quedarse un tanto bloqueada mientras calcula.

El resumen es que Python tiene una precisión ilimitadamente grande en los enteros mientras tenga recursos disponibles, un detalle sorprendente para cualquiera que este acostumbrado a programar en otros lenguajes, y una de las razones por las que Python se ha convertido en lenguaje de facto para la ciencia y especialmente para la investigaciones numéricas.

Práctica: crear un fichero llamado hello.py que saque por pantalla el texto “Hola Mundo” desde consola conectado por ssh y ejecutarlo.

Más información: Introducción a Python.

Variables y Tipos de Datos en Python

Una variable es algo parecido a un contenedor o cajón con un nombre. Una cosa es el nombre del cajón y otra su contenido y conviene entender desde ya la diferencia.

Las variables pueden tomar distintos valores e ir cambiandolo en función del programa, de la misma manera que un cajón puede ir variando su contenido sin que se mueva de sitio.

En Python no es necesario definir las variables antes de usarlas, a diferencia de C y similares. Basta con que la declares asignándole un valor.

Por ejemplo escribe directamente:

  • base = 86
  • iva = base * 0.21
  • total = base + iva
  • print (total)
  • print(base, iva, total)
  • base = input (“Dame el precio del artículo, por favor : “)
  • print(base + base * 0.21)
  • type(base)
  • print (int(base) + int(base) * 0.21)
  • iva = float(base) * 0.21
  • print (int(base) +iva)

Práctica: Hacer un programa llamado iva.py y que pida el valor del articulo y devuelva el valor con iva.

Más información: Variables y tipos en Python.

En Python existen 4 tipos diferentes de variables numéricas:

  • int Número entero con precisión fija (ℤ).
  • long Número entero en caso de sobrepasar el tamaño de un int.
  • float Número en coma flotante de doble precisión (ℝ).
  • complex Número complejo (parte real + j parte imaginaria) (ℂ)

Una función muy útil, que sirve para conocer el tipo de una variable es: type()

El tipo booleano es un tipo de variable que sólo puede contener dos valores: True y False.

Se definen como caracteres entre comillas simples ‘ o dobles “.

Tipo listas

Se definen poniendo el contenido de la lista entre corchetes, separando cada uno de los elementos mediante una coma. Cada posición de la lista puede contener elementos de distinto tipo. Además, las listas son mutables, es decir, sus elementos pueden ser modificados. En Python los elementos de una lista se numeran desde 0 hasta longitud−1.Hay numerosas funciones que pueden aplicarse a una lista.

Para acceder al elemento de una lista se pone el nombre de la lista y a continuación el índice al que queremos acceder entre corchetes(si ponemos el índice con signo negativo empezará por el final de la lista). Para acceder a un rango dentro de una lista tenemos diferentes opciones:

  • Desde el inicio tomar a elementos (no incluye a):
    lista[:a]
  • Desde la posición a (incluida) tomar todos los elementos hasta el final
    lista[a:]
  • Tomar los elementos desde a hasta b (sin incluir b)
    lista[a:b]

Las listas tienen asociadas una serie de métodos que permiten una gran variedad de operaciones sobre ellas:

  • .append(), añade un elemento al final de la lista.
  • .insert(), se usa para insertar un elemento en el índice asignado.
  • .pop(), elimina y devuelve el valor en la posición del índice asignado.
  • .reverse(), reordena la lista de forma reversa.
  • .sort(), reordena la lista de forma ascendente.

Más en listas: https://docs.python.org/3/tutorial/datastructures.html#more-on-lists

Ejercicio: probar estos ejemplos de listas 

Tipo tuplas

Las tuplas son similares a las listas, se definen con paréntesis en vez de corchetes. Tienen la peculiaridad de ser inmutables.

Tipo diccionarios

Los diccionarios definen una relación uno a uno entre claves y valores y son mutables. Se definen colocando una lista separada por comas de pares clave:valor. Una vez definido, podemos acceder al valor asociado a una clave buscando por la clave. Además, podemos buscar si una determinada clave existe o no en nuestro diccionario.

Los diccionarios se definen con {}

  • .keys()
  • .values()
  • .items() – devuelve una lista de tuplas clave – valor del diccionario

zip me permite coger dos listas y hacer un diccionario: diccionario = dict(zip(lista_claves,lista_valores))

del(diccionario[‘clave’]) – borra la entrada de un diccionario

Ojo, al copiar un diccionario con ciudades_2 = ciudades, no creo una copia sino dos variables que apuntan a un mismo objeto.

id(diccionario) – me devuelve el número del puntero al diccionario

ciudades_2 = ciudades.copy() -> así tengo una copia independiente de un diccionario

Ejercicio: ejecucar algunos ejemplos con diccionarios https://recursospython.com/guias-y-manuales/diccionarios/

Ver:

Operadores aritméticos

Las diferentes operaciones aritméticas en Python son los siguientes:

  • +
  • ∗∗  – elevado
  • / – división entera
  • // – división
  • %

Operadores de asignación

Los diferentes operadores de asignación en Python son los siguientes:

  • =: Asigna a la variable del lado derecho aquello que pongamos en el lado derecho.
  • +=: Suma a la variable del lado izquierdo la variable del lado derecho.
  • −=: Resta a la variable del lado izquierdo la variable del lado derecho.
  • ∗=: Multiplica la variable del lado izquierdo por la variable del lado derecho.
  • /=: Divide la variable del lado izquierdo por la variable del lado derecho.
  • ∗∗=: Eleva la variable de la izquierda a la potencia de la variable de la derecha.
  • //=: División entera de la variable de la izquierda entre la de la derecha.
  • %=: Resto de la división de la variable de la izquierda entre la de la derecha.

Operadores relacionales

Los operadores relacionales de Python son:

  • ==: Evalúa que los valores sean iguales.
  • !=: Evalúa que los valores sean distintos.
  • <: Evalúa que el valor de la izquierda sea menor que el de la derecha.
  • >: Evalúa que el valor de la izquierda sea mayor que el de la derecha.
  • <=: Evalúa que el valor de la izquierda sea menor o igual que el de la derecha.
  • >=: Evalúa que el valor de la izquierda sea mayor o igual que el de la derecha.
  • not: negación de una variable booleana

Librerías

Python es un lenguaje pensado para ser ampliado con lo necesario y hace tiempo que se ha convertido en el pilar de la investigación en numerosos campos de ciencia y tecnología

Disponemos de infinidad de librerías que podemos usar llamando a la clausula import

La librería estándar de python incluye muchos módulos: https://docs.python.org/dev/library/index.html

Ejecutar:

  • from fractions import *
  • F1 = Fraction(2,3)
  • F2 = Fraction(3,4
  • print(F1, F2)
  • print (F1 + F2)
  • print (F1 * F2)
  • print (F1 / F2)
  • import math
  • math.factorial(4)
  • math.factorial(432)
  • import numpy
  • a = numpy.array(([1,2,3],[4,5,6],[7,8,9]))
  • print (a)
  • print (a * a)
  • from matplotlib import pyplot
  • pip install matplot lib
  • x = numpy.linspace(0, 2 * numpy.pi, 100)
  • y = numpy.sin(x)
  • pyplot.plot(x, y)
  • pyplot.show()

NumPy es una extensión de Python, que le agrega mayor soporte para vectores y matrices, constituyendo una biblioteca de funciones matemáticas de alto nivel para operar con esos vectores o matrices.

Estos módulos externos que podemos descargar e importar a nuestros programas reciben en Python el nombre de packages. Existen packages que podemos importar, más o menos estándar para lo que se te ocurra.

Python Package Index: https://pypi.org/

Más información: Imports en Python

Módulos en Python: http://research.iac.es/sieinvens/python-course/source/modulos.html

Módulos y paquetes: https://www.learnpython.org/en/Modules_and_Packages 

Diferencia entre módulos, Paquetes y librerías

Standar Library: https://docs.python.org/3/library/ 

Métodos de instalación de Paquetes:

Como instalar y usar pip: https://pip.pypa.io/en/latest/installing.html

Por defecto estos gestores de paquetes buscan en https://pypi.org/

El Python Package Index o PyPI es el repositorio de software oficial para aplicaciones de terceros en el lenguaje de programación Python. Los desarrolladores de Python pretenden que sea un catálogo exhaustivo de todos los paquetes de Python escritos en código abierto. https://es.wikipedia.org/wiki/%C3%8Dndice_de_paquetes_de_Python

Para ver la ruta de los paquetes:

  • import sys
  •  print (‘\n’.join(sys.path))

Para ver los módulos instalados: pip freeze o pip list

Para actualizar ejecutar: pip install –upgrade pip

Instalar paquetes de Python: https://www.raspberrypi.org/documentation/linux/software/python.md

Sentencias condicionales

Imaginemos que queremos crear un sistema automático de riego en nuestra casa, de forma que cuando la lectura de un sensor de humedad sea menor que un cierto valor, encienda el sistema y que si la lectura es mayor que un cierto valor, lo apague. Con las herramientas que tenemos hasta ahora, esto no sería posible, para esto utilizamos la sentencia if/elif/else, que tiene la siguiente estructura:

if <expresion_booleana>:   # Solo si la condicion booleana es True, 

    bloque codigo          # el bloque de código se ejecuta

    …

elif <expresion_booleana>: # No es necesario, añade condiciones extra al conjunto.

    bloque codigo          # Se puede poner tantas como se necesiten.

    …

else:                      # No se necesario. Se ejecuta solo si

    bloque codigo          # todas las condiciones anteriores son falsas.         

    …

Nota: Es importante saber la importancia de la indentación en Python. Cuando usemos sentencias que acaben en “:” (if, for…) las líneas que estén dentro de esta sentencia irán después de un tabulador o 4 espacio, como se muestra en los ejemplos.

Ejemplo:

num = float(input(“Enter a number: “))

if num >= 0:

    if num == 0:

        print(“Zero”)

    else:

        print(“Positive number”)

else:

    print(“Negative number”)

Más información: El tipo Bool y sus operaciones.

Sentencias bucle

Anteriormente hemos visto el tipo de variable lista. Estas contenían una cierta cantidad de elementos. Imaginemos que tenemos una lista de enteros y queremos mostrar por pantalla los elementos que contiene que sean mayores que 5. Para esto, entre otras cosas, tenemos sentencias bucle.

En Python existen dos tipos estructuras de bucles:

  • Bucles for
  • Bucles while

La sintaxis de un bucle for es:

for <variable_sin_definir> in <Iterable>: # El bloque se ejecuta tantas veces 

    bloque codigo                         # como elementos tiene el iterable

    …

El blucle ejecuta un bloque de código tantas veces como esté definido. El número de veces que se recorre el bucle es equivalente al número de elementos en el iterable que se usa. La variable que se usa toma como valores los elementos del iterable de forma secuencial, un valor por cada iteración.

Los bucles for son una gran herramienta para recorrer todos los elementos de una colección.

Ejemplo:

fruits = [“apple”, “banana”, “cherry”]

for x in fruits:

  print(x)

Ejemplo:

for x in range(6):

  print(x)

else:

  print(“Finally finished!”)

La sintaxis de los bucles while es:

while <condicion_boolena>:   # El bloque se ejecuta hasta que la condición es falsa.

    bloque codigo            # Antes de ejecutar asegurarse que se va a salir.

    …

El bucle while se ejecuta de forma indefinida hasta que la condición después del while sea falsa. Por lo tanto es necesario realizar un cambio dentro del bucle que finalmente hará que se vuelva la condición False.

Adicionalmente existen un par de comandos dentro de Python que sirven para tener más control sobre los bucles:

  • continue. El intérprete cuando lo lee termina de ejecutar la presente iteración y pasa a la siguiente iteración.
  • break . El intérprete cuando lo lee termina la ejecución del bucle, continuando la ejecución de las siguientes líneas.

Ejemplo:

i = 1

while i < 6:

  print(i)

  if i == 3:

    break

  i += 1

Más información: Mas sobre Python for y While.

Iteradores

En Python existen diferentes estructuras que son conjuntos de elementos, son las llamadas colecciones. Este tipo de estructuras son iterables, es decir, se pueden recorrer elemento por elemento. Como veíamos antes, el bucle for itera sobre un iterable, por lo que utilizamos esta sentencia para recorrerlos. Algunos tipos de variable que son iterables son:

  • Cadena de caracteres (str)
  • Lista (list)
  • Tupla (tuple)
  • Diccionario (dict)

Además, muchas veces queremos repetir un bucle un número determinado de veces. Para esto puede ser útil la función range(n). Esta función genera un iterable que va desde 0 hasta n-1.

Más información:Iteraciones for en Python 3.

Funciones

Es muy posible que a lo largo de un programa necesitemos calcular el factorial de un número. Podemos escribir el código necesario para calcularlo en cada punto que lo necesitamos, o crear una función que podamos llamar desde cualquier punto y nos calcule el factorial de un número. 

La sintaxis para definir una función en Python es la siguiente:

def nombre_funcion(<parametro1>, <parametro2>, …): # Los parametros son opcionales

    Bloque codigo

    …

    return <valor_a_devolver> # El comando es opcional (puede devolver varios valores)

Los parámetros son las variables que se definen dentro del paréntesis, separados por comas. Son opcionales y sirven para pasarle valores a la función. Son opcionales una vez definimos la función, pero si la función está definida con n argumentos, tendremos que informarlos.

Adicionalmente puede introducirse una sentencia return que termina la ejecución de la función y devuelve el valor/objeto que está colocado justo después.

Los nombres de las funciones sigue el mismo convenio que el de las variables.

Para llamar a una función, como hemos visto antes, tenemos que escribir el nombre de la función y añadir entre paréntesis los argumentos que la funció necesita. Aunque la función no necesite argumentos, tenemos que escribir los paréntesis.

Ejemplo:

def escribe_media(x, y):

    media = (x + y) / 2

    print(f”La media de {x} y {y} es: {media}”)

    return

a = 3

b = 5

escribe_media(a, b)

print(“Programa terminado”)

Código de python (ejemplos y snippets):

Ejemplos de Python aplicados a la Industria

Ejemplos:

Ejercicio: Recoger datos meteorológicos de aemet

Aemet Open data: http://www.aemet.es/es/datos_abiertos/AEMET_OpenData

Obtener Api Key: https://opendata.aemet.es/centrodedescargas/inicio

Documentación de la API: https://opendata.aemet.es/dist/index.html?

Ejemplo programa Python: https://opendata.aemet.es/centrodedescargas/ejemProgramas?

Crear un ejemplo usando la librería requests: https://pypi.org/project/requests/ y ejecutar para logroño.

Código: https://github.com/jecrespo/Aprendiendo-RaspberryPi/blob/master/Ejercicio03-Aemet/aemet.py

Librería: https://pypi.org/project/python-aemet/

No hay librería de AEMET en Node-RED, pero podemos hacer las peticiones a la web como se ha hecho en python.

Prácticas: Variables y Tipos de Datos en Arduino

Montaje Arduino UNO:

Montaje Wemos:

Ejercicio07 – Ámbito Variables

Ámbito de las variables en C++

Ejercicio07: Mover el servo mediante el botón A. Para ello cada vez que se pulse mover 10 grados y cuando llegue a 170 grados volver a la posición inicial de 10 grados.

Usar una una variable llamada “grados” que aumente su valor cada vez que se detecte un flanco ascendente. Hacerlo como variable local y global.

Hacer una función “detectaFlanco” que use una variable local para detectar flanco.

Sacar por el puerto serie el ángulo que está, por la pantalla LCD y por el Serial Plotter

Solución: https://codeshare.io/GAoV7v

Hacer commit y pull del código en el repositorio “Curso Programacion Arduino 2019” que esté en una carpeta llamada Ejercicio07-Ambito_Variables

Ejercicio08 – Puntuaciones

Hacer un programa,de forma que muestre por la pantalla LCD el valor del LDR y un contador de puntos. Al pulsar un botón A, acumule el valor del LDR multiplicado por 10 hasta un máximo de 8 pulsaciones y luego empiece en cero. Ver quién consigue más puntos. ¿Quién llegará a 80000 puntos?

Solución: https://codeshare.io/5OY4ZP

Hacer commit y pull del código en el repositorio “Curso Programacion Arduino 2019” que esté en una carpeta llamada Ejercicio08-Puntuaciones

Ejercicio09 – Puntuaciones Wemos

Adaptar el código del Ejercicio09-Puntuaciones_Wemos para el Wemos D1 Mini con la pantalla oled.

Comprobar cómo adaptar un código de una placa a otra y con componentes diferentes

NOTA: conectar el LDR al pin A0 del Wemos D1 Mini

Solución: https://codeshare.io/5eey47

Hacer commit y pull del código en el repositorio “Curso Programacion Arduino 2019” que esté en una carpeta llamada Ejercicio09-Puntuaciones_Wemos

Variables en Arduino

¿Que es una variable? Una variable es un lugar donde almacenar un dato, tiene un nombre, un valor y un tipo.

Los nombres de variables pueden tener letras, números y el símbolo ’_’. Deben empezar por una letra (pueden empezar por ’_ ’ pero no es recomendable pues es el criterio que usan las rutinas de la biblioteca).

Pueden llevar mayúsculas y minúsculas. En C se distingue entre mayúsculas y minúsculas. La costumbre es que las variables van en minúscula y las constantes en mayúscula

Usa las mismas reglas dentro del código para el nombramiento de variables, ya sea en minúscula con palabras separadas con guiones bajos, tantos como sea necesario para mejorar la legibilidad o utilizar la convención “CapWords” (palabras que comienzan con mayúsculas), aunque generalmente la primera palabra se pone en minúsculas.

Usa un solo guión bajo como prefijo para métodos no públicos y variables de instancia.

Las palabras reservadas if, else,etc . . . no pueden usarse como nombres de variables.

Nombres para evitar: Nunca uses los caracteres ‘l’ (letra ele en minúscula), ‘O’ (letra o mayúscula), o ‘I’ (letra i mayúscula) como simples caracteres para nombres de variables, para evitar confusiones a la hora de leer el código.

Declaración de variables.

Una variable tiene un nombre, un valor y un tipo. Con la asignación, se puede cambiar el valor de la variable.

Todas las variables deben ser declaradas antes de su uso. Las declaraciones deben aparecer al principio de cada función o bloque de sentencias. Al declarar una variable se debe indicar primero el tipo de variable y luego su nombre, opcionalmente se le puede dar un valor, lo que se llama inicializar la variable.

La declaración consta de un tipo de variable y una lista de variables separadas por coma.

  • int i,j;
  • float x,pi;
  • unsigned long longitud, contador;

Las variables pueden inicializarse en la declaración

  • float pi=3.1416;
  • unsigned long contador=0;

Puede utilizarse el modificador const para indicar que la variable no puede ser cambiada en tiempo de ejecución.

  • const float e=2.7182;

La declaración de una variable sólo debe hacerse una vez en un programa, pero el valor de la variable se puede cambiar en cualquier momento usando aritmética y reasignaciones diversas.

Una variable puede ser declarada en una serie de lugares del programa y en función del lugar en donde se lleve a cabo la declaración, esto determinará en qué partes del programa se podrá hacer uso de ella, es lo que se denomina ámbito de la variable o scope.

C y C++ se dice que son lenguajes de tipado estático, es decir, la comprobación de tipificación se realiza durante la compilación, y no durante la ejecución, por lo tanto no podemos cambiar el tipo de una variable en tiempo de ejecución. Otros lenguajes, generalmente interpretados, son de tipado dinámico y una misma variable puede tomar valores de distinto tipo en distintos momentos, como PHP o python.

La explicación de www.arduino.cc de las variables: http://arduino.cc/en/Tutorial/Variables y http://arduino.cc/en/Reference/VariableDeclaration

Usando Visualino tenemos de un apartado de variables donde tenemos los bloques para declarar, asignar y llamar las variables.

Ámbito de una variable

Una variable puede ser declarada al inicio del programa antes de la parte de configuración setup(), a nivel local dentro de las funciones, y, a veces, dentro de un bloque, como para los bucles del tipo if.. for.., etc. En función del lugar de declaración de la variable así se determinará el ámbito de aplicación, o la capacidad de ciertas partes de un programa para hacer uso de ella.

Una variable global es aquella que puede ser vista y utilizada por cualquier función y estamento de un programa. Esta variable se declara al comienzo del programa, antes de setup().

Recordad que al declarar una variable global, está un espacio en memoria permanente en la zona de static data y el abuso de variables globales supone un uso ineficiente de la memoria.

Una variable local es aquella que se define dentro de una función o como parte de un bucle. Sólo es visible y sólo puede utilizarse dentro de la función en la que se declaró. Por lo tanto, es posible tener dos o más variables del mismo nombre en diferentes partes del mismo programa que pueden contener valores diferentes, pero no es una práctica aconsejable porque complica la lectura de código.

En el reference de Arduino hay una muy buena explicación del ámbito de las variables: http://arduino.cc/en/Reference/Scope

Con Visualino es posible declarar variables locales y globales:

El modificador de variable static, es utilizado para crear variables que solo son visibles dentro de una función, sin embargo, al contrario que las variables locales que se crean y destruyen cada vez que se llama a la función, las variables estáticas mantienen sus valores entre las llamadas a las funciones.

La variables estáticas solo se crean e inicializan la primera vez que la función es llamada. Ver ejemplo en: http://arduino.cc/en/Reference/Static

Con Visualino no es posible declarar variables estáticas.

Probar este ejercicio y luego añadir static a la variable valor. Ver la diferencia.

Solución: https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_2017/tree/master/Ejercicio03-Visualino_Variables

Constantes

En programación, una constante es un valor que no puede ser alterado/modificado durante la ejecución de un programa, únicamente puede ser leído. Una constante corresponde a una longitud fija de un área reservada en la memoria principal del ordenador, donde el programa almacena valores fijos. Por ejemplo el valor de PI = 3.1416.

El modificador const, modifica el comportamiento de una variable haciéndola “read-only”, esto significa que puede usarse como cualquier otra variable pero su valor no puede ser cambiado.

Más información en: http://arduino.cc/en/Reference/Const

El entorno de programación de Aduino también tiene predefinidas unas constantes o expresiones, que facilitan la lectura del código: http://arduino.cc/en/Reference/Constants

En C++ las constantes también pueden ser definidas a nivel de módulo antes de compilar, de forma que no ocupan memoria y su nombre es sustituido por el valor definido en el proceso de compilación. Estas constantes por norma se escriben con letras en mayúscula y guiones bajos separando palabras. Por ejemplo, MAX_OVERFLOW y TOTAL. Se usa la palabra clave #define para definirlas.

Más información en: https://www.arduino.cc/en/Reference/Define

En Visualino no está disponible la opción de declarar constantes, pero se pueden declarar variables globales y luego añadir el modificador const.

Repaso Programación Arduino

El lenguaje de programación de Arduino es C++. No es un C++ puro sino que es una adaptación que proveniente de avr-libc que provee de una librería de C de alta calidad para usar con GCC (compilador de C y C++) en los microcontroladores AVR de Atmel y muchas utilidades opensource específicas para las MCU AVR de Atmel como avrdude: https://learn.sparkfun.com/tutorials/pocket-avr-programmer-hookup-guide/using-avrdude

Las herramientas necesarias para programar los microcontroladores AVR de Atmel son avr-binutils, avr-gcc y avr-libc y ya están incluidas en el IDE de Arduino, pero cuando compilamos y cargamos un sketch estamos usando estas herramientas.

Aunque se hable de que hay un lenguaje propio de programación de Arduino, no es cierto, la programación se hace en C++ pero Arduino ofrece unas librerías, también llamado core, que facilitan la programación de los pines de entrada y salida y de los puertos de comunicación, así como otras librerías para operaciones específicas. El propio IDE ya incluye estas librerías de forma automática y no es necesario declararlas expresamente. Otra diferencia frente a C++ standard es la estructuctura del programa ya que no usa la función main(), sino que usa las funciones setup() y loop().

En la mayoría de los casos se puede hacer un proyecto de Arduino de cierta complejidad con la librería que nos ofrece el core de Arduino y no es necesario añadir más instrucciones ni tipos de datos que los que hay en el core. Pero cuando queremos algo más complejo o más rápido o menos consumo o con más memoria, etc… es necesario usar funciones y estructuras no disponibles en el core de Arduino.

Toda la información para programar con el core de Arduino se encuentra en el reference de la web de Arduino: https://www.arduino.cc/en/Reference/HomePage

Una buena chuleta para tener a mano cuando programemos. Cheat Sheet: https://dlnmh9ip6v2uc.cloudfront.net/learn/materials/8/Arduino_Cheat_Sheet.pdf

Lenguaje de programación C++

Es posible usar comandos estándar de C++ en la programación de Arduino siempre que estén incluidos en el avr libc:

En Internet hay muchas webs de referencia donde consultar dudas a la hora de programar en C++:

Un manual sencillo de entender para la programación es el “arduino programming notebook” de brian w. Evans. Puedes consultarlo o descargarlo desde:

Cuando compilamos y cargamos el programa en Arduino esto es lo que ocurre:

Variables

Una variable puede ser declarada al inicio del programa antes de la parte de configuración setup(), a nivel local dentro de las funciones, y, a veces, dentro de un bloque, como para los bucles del tipo if.. for.., etc. En función del lugar de declaración de la variable así se determinará el ámbito de aplicación, o la capacidad de ciertas partes de un programa para hacer uso de ella.

Una variable global es aquella que puede ser vista y utilizada por cualquier función y estamento de un programa. Esta variable se declara al comienzo del programa, antes de setup().

Recordad que al declarar una variable global, está un espacio en memoria permanente en la zona de static data y el abuso de variables globales supone un uso ineficiente de la memoria.

Una variable local es aquella que se define dentro de una función o como parte de un bucle. Sólo es visible y sólo puede utilizarse dentro de la función en la que se declaró. Por lo tanto, es posible tener dos o más variables del mismo nombre en diferentes partes del mismo programa que pueden contener valores diferentes, pero no es una práctica aconsejable porque complica la lectura de código.

En el reference de Arduino hay una muy buena explicación del ámbito de las variables: http://arduino.cc/en/Reference/Scope

El modificador de variable static, es utilizado para crear variables que solo son visibles dentro de una función, sin embargo, al contrario que las variables locales que se crean y destruyen cada vez que se llama a la función, las variables estáticas mantienen sus valores entre las llamadas a las funciones.

Los tipos de variables en Arduino son:

Además de usar este tipo de datos que son los que aparecen en el reference de Arduino (https://www.arduino.cc/en/Reference/HomePage), es posible usar cualquier tipo de variable de C++ estándar con las limitaciones propias de cada microcontrolador.

Tipos de variables estándar en C++:

Más información sobre los tipos de variable Arduino en: https://aprendiendoarduino.wordpress.com/2016/06/29/tipos-de-datos-2/

Arrays

Un array es un conjunto de valores a los que se accede con un número índice. Cualquier valor puede ser recogido haciendo uso del nombre de la matriz y el número del índice. El primer valor de la matriz es el que está indicado con el índice 0, es decir el primer valor del conjunto es el de la posición 0. Un array tiene que ser declarado y opcionalmente asignados valores a cada posición antes de ser utilizado.

Para manejar arrays en C++ dispones de las funciones estándar: http://www.cplusplus.com/reference/array/array/

string (char array)

Un string es un array de chars. Cuando se trabaja con grandes cantidades de texto, es conveniente usar un array de strings. Puesto que los strings son en si mismo arrays de chars.

Reference de Arduino para string: https://www.arduino.cc/en/Reference/String

Para manejara strings (char array) disponemos de las funciones de string.h que define diversas funciones para manipular strings y arrays http://www.cplusplus.com/reference/cstring/

También es posible usar la clase string de C++: http://www.cplusplus.com/reference/string/string/

Más información para aclarar la diferencia entre string y la clase string: https://www.tutorialspoint.com/cplusplus/cpp_strings.htm

String (Objeto)

Se trata de una clase que permite usar y manipular cadenas de texto de una forma más sencilla que los strings. Puedes concatenar, añadir, buscar, etc… usando los métodos/funciones que ofrece esta clase.

Toda la información de la clase String en el reference de Arduino https://www.arduino.cc/en/Reference/StringObject

Los Strings tienen un uso intensivo de memoria, pero son muy útiles y se van a utilizar mucho en el apartado de comunicación, por ese motivo es importante aprender a manejar los Strings.

Tener en cuenta que al no ser un tipo de dato propiamente dicho sino una clase, tienes unas funciones asociadas (métodos), operadores y unas propiedades. Es una abstracción del dato y para aprender a usarlo hay que leerse la documentación correspondiente.

Operadores

El core de Arduino ofrece una serie de operadores según su reference:

Pero además es posible usar los operadores estnándar de C /C++ y más información: http://es.wikipedia.org/wiki/Anexo:Operadores_de_C_y_C%2B%2B

Estructuras de control

Las estructuras de control en Arduino según el reference son:

Funciones definidas por usuario

Una función es un bloque de código que tiene un nombre y un conjunto de instrucciones que son ejecutadas cuando se llama a la función. Son funciones setup() y loop() de las que ya se ha hablado.

Las funciones de usuario pueden ser escritas para realizar tareas repetitivas y para reducir el tamaño de un programa. Segmentar el código en funciones permite crear piezas de código que hacen una determinada tarea y volver al área del código desde la que han sido llamadas.

Más información sobre las funciones en C++: http://www.cplusplus.com/doc/tutorial/functions/

Práctica: Menú Interactivo

Hacer un menú interactivo a través del puerto serie donde al pulsar la opción 1 enciende el led del pin 9, al pulsar la opción 2 apaga el led del pin 9 y al pulsar la opción 3 mido el voltaje que tengo en la entrada analógica A0 conectada a un potenciómetro y la muestra por pantalla.

Instalación:

Solución Ejercicio16: https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_Avanzado_2017/tree/master/Ejercicio16-Menu_Interactivo

Prácticas: Función Detecta Flanco y Dado Digital

Hacer los dos ejercicios de https://aprendiendoarduino.wordpress.com/2017/07/07/practica-funciones/

Para ejercicio detecta flanco, el montaje son dos botones en los pines 2 y 3.

Solución Detecta Flanco: https://github.com/jecrespo/aprendiendoarduino-Curso_Programacion_Arduino/tree/master/Ejercicio09-Funcion_Detecta_Flanco

La función detecta flanco solo funciona con un pulsador, pero cuando se intenta usar con dos pulsadores ya no funciona, la solución es crear un objeto.

Código para detectar flanco en dos pulsadores que falla: https://github.com/jecrespo/aprendiendoarduino-Curso_Programacion_Arduino/blob/master/Ejercicio09-Funcion_Detecta_Flanco_Error/Ejercicio09-Funcion_Detecta_Flanco_Error.ino

Función detecta flanco:

 
int detectaFlanco(int pin) {
  //Devuelve 1 flanco ascendente, -1 flanco descendente y 0 si no hay nada
  static boolean anterior_estado = digitalRead(pin);
  boolean estado = digitalRead(pin);

  if (anterior_estado != estado) {
    if (estado == HIGH) {
      anterior_estado = estado;
      return 1;
    }
    else {
      anterior_estado = estado;
      return -1;
    }
  }
  else {
    return 0;
  }
}

Solución Ejercicio Dado: https://github.com/jecrespo/aprendiendoarduino-Curso_Programacion_Arduino/tree/master/Ejercicio10-Dado

Práctica: Ámbito de la Variables

Ámbito de las variables en C++

Ejercicio05: Mover el servo mediante el botón A. Para ello cada vez que se pulse mover 10 grados y cuando llegue a 170 grados volver a la posición inicial de 10 grados.

Usar una una variable llamada “grados” que aumente su valor cada vez que se detecte un flanco ascendente. Hacerlo como variable local y global.

Hacer una función “detectaFlanco” que una una variable local para detectar flanco.

Sacar por el puerto serie el ángulo que esta y verlo por el Serial Plotter

Github: https://github.com/curso-programacion-arduino/Ejercicio05.git

Solución: https://github.com/jecrespo/aprendiendoarduino-Curso_Programacion_Arduino