Thursday, September 2, 2021

Gimbal Adapter Radiomaster TX16S-Flysky FS-HZCZ03-ADJ






 

The following components are needed:

- 2x PETG adapter plates with 4xM2 nut insert pre-mounted.

- 1x adapter cable

- 4x M2 nut

- 4x M2x6 screw

- 4x M2x12 screw





How to replace the TX16S gimbals with Flysky gimbals:


1. Dismount the original gimbal (keep the 8 screws, will be needed for the adapter plate).

2. Mount the 2 PETG adapter plates with the 8 original gimbal screws.(Don't overtighten the screws!)

3. Mount the 4 M2 nuts in the outer position of the adapter plates like shown in the following video:



4. Mount the Flysky gimbals with 4xM2x6 and 4xM2x12 screws. (Don't overtighten the screws!)

5. Connect the adapter cable between gimbal and TX16S main board.




The Flysky gimbals are supported (currently) only with EdgeTX Firmware. Here is the Wiki page: Gimbal Flysky Mod EdgeTX


You can get all the necessary items for the mod from here: Gimbal Adapter TX16S-Flysky

Monday, June 24, 2019

How to fix PMU Problems with X9-Lite (External Module not powered)

Here is a fix for the problem. With this solution you only bypass the useless PMU introduced by Frsky that is not working at all. The PMU is an unknown MCU. The surface is scratched so is not recognizable.

This method just connect the MCU STM32 PIN PA8 to the mosfet that provide VMAIN, that is the power supply to the external module. With only a short cable it is fixed. I couldnt test it a lot, but for now it is working fine.

I am glad if it fix the Problem for you.

Best regards,




Thursday, April 20, 2017

Porgrama para el cubo con LEDS WS2812

Hola, aquí os dejo el código para programar el cubo con LEDS. Es un firmware en desarrollo, todavía tiene fallos y lo iré actualizando.



Aquí os dejo también un boceto que me hice para calcular el cambio de coordenadas para los LEDS.



Un saludo.


// NeoPixelTest
// This example will cycle between showing four pixels as Red, Green, Blue, White
// and then showing those pixels as Black.
//
// Included but commented out are examples of configuring a NeoPixelBus for
// different color order including an extra white channel, different data speeds, and
// for Esp8266 different methods to send the data.
// NOTE: You will need to make sure to pick the one for your platform
//
//
// There is serial output of the current state so you can confirm and follow along
//
//#include <NeoPixelBus.h>

#include <NeoPixelBrightnessBus.h> // instead of NeoPixelBus.h

#include "IRLibAll.h"

#define PIN_CHR 3
#define PIN_FULL 9
#define PIN_ADC 0

#define STATUS_CHR 0
#define STATUS_1  1
#define STATUS_2  2
#define STATUS_3  3
#define STATUS_4  4
#define STATUS_5  5
#define STATUS_6  6
#define STATUS_OFF 7

#define LEDS_OFF 0
#define LEDS_ON 1

int RECV_PIN = 2;
//volatile bool ir_flag = false;

unsigned char status_cube = STATUS_OFF;
unsigned char status_leds = LEDS_OFF;
uint8_t brightness = 50;   //between 8 and 255

IRrecvPCI myReceiver(RECV_PIN); //create receiver and pass pin number
IRdecode myDecoder;   //create decoder

const uint16_t PixelCount = 192; // this example assumes 4 pixels, making it smaller will cause a failure
const uint8_t PixelPin = 4;  // make sure to set this to the correct pin, ignored for Esp8266 //default 2

#define colorSaturation 128

// three element pixels, in different order and speeds
//NeoPixelBus<NeoGrbFeature, Neo800KbpsMethod> strip(PixelCount, PixelPin);   //default

NeoPixelBrightnessBus<NeoGrbFeature, Neo800KbpsMethod> strip(PixelCount, PixelPin);

//NeoPixelBus<NeoRgbFeature, Neo400KbpsMethod> strip(PixelCount, PixelPin);

// For Esp8266, the Pin is omitted and it uses GPIO3 due to DMA hardware use.
// There are other Esp8266 alternative methods that provide more pin options, but also have
// other side effects.
//NeoPixelBus<NeoGrbFeature, Neo800KbpsMethod> strip(PixelCount);
//
// NeoEsp8266Uart800KbpsMethod uses GPI02 instead

// You can also use one of these for Esp8266,
// each having their own restrictions
//
// These two are the same as above as the DMA method is the default
// NOTE: These will ignore the PIN and use GPI03 pin
//NeoPixelBus<NeoGrbFeature, NeoEsp8266Dma800KbpsMethod> strip(PixelCount, PixelPin);
//NeoPixelBus<NeoRgbFeature, NeoEsp8266Dma400KbpsMethod> strip(PixelCount, PixelPin);

// Uart method is good for the Esp-01 or other pin restricted modules
// NOTE: These will ignore the PIN and use GPI02 pin
//NeoPixelBus<NeoGrbFeature, NeoEsp8266Uart800KbpsMethod> strip(PixelCount, PixelPin);
//NeoPixelBus<NeoRgbFeature, NeoEsp8266Uart400KbpsMethod> strip(PixelCount, PixelPin);

// The bitbang method is really only good if you are not using WiFi features of the ESP
// It works with all but pin 16
//NeoPixelBus<NeoGrbFeature, NeoEsp8266BitBang800KbpsMethod> strip(PixelCount, PixelPin);
//NeoPixelBus<NeoRgbFeature, NeoEsp8266BitBang400KbpsMethod> strip(PixelCount, PixelPin);

// four element pixels, RGBW
//NeoPixelBus<NeoRgbwFeature, Neo800KbpsMethod> strip(PixelCount, PixelPin);

RgbColor red(colorSaturation, 0, 0);
RgbColor green(0, colorSaturation, 0);
RgbColor blue(0, 0, colorSaturation);
RgbColor white(colorSaturation);
RgbColor black(0);
RgbColor yellow(colorSaturation,colorSaturation,0);
RgbColor orange(colorSaturation,colorSaturation / 2,0);

HslColor hslRed(red);
HslColor hslGreen(green);
HslColor hslBlue(blue);
HslColor hslWhite(white);
HslColor hslBlack(black);
HslColor hslYellow(yellow);
HslColor hslOrange(orange);

unsigned int xy2pixel(unsigned int x,unsigned int y){
  unsigned int pixel;
  unsigned int face;
  unsigned int u = 0;
  unsigned int v = 0;
  if( x>= 0 && x<=14) face = 0;
  else if(x > 14 && x < 30) face = 1;
  else if(x >= 30 && x <= 44) face = 2;

  x = x % 15;

  //transform x,y to u,v
  u = (x - 7 + y) / 2;
  v = (7 - x + y) / 2;

  //transform u,v to pixel number
  pixel = (face * 64) + 56 + u - (8 * v);
//  Serial.print("Pos x:");
//  Serial.print(x);
//  Serial.print("Pos y:");
//  Serial.print(y);
//  Serial.print("Pos u:");
//  Serial.print(u);
//  Serial.print("Pos v:");
//  Serial.print(v);
//  Serial.print("Face:");
//  Serial.print(face);
//  Serial.print("Pixel:");
//  Serial.println(pixel);
  return pixel;
}

bool validxy(unsigned int x,unsigned int y){
  x = x % 15;
  if(x == 0 && y == 7) return true;
  if(x == 1 && (y == 6 || y == 8)) return true;
  if(x == 2 && (y == 5 || y == 7 || y == 9)) return true;
  if(x == 3 && (y == 4 || y == 6 || y == 8 || y == 10)) return true;
  if(x == 4 && (y == 3 || y == 5 || y == 7 || y == 9 || y == 11)) return true;
  if(x == 5 && (y == 2 || y == 4 || y == 6 || y == 8 || y == 10 || y == 12)) return true;
  if(x == 6 && (y == 1 || y == 3 || y == 5 || y == 7 || y == 9 || y == 11 || y == 13)) return true;
  if(x == 7 && (y == 0 || y == 2 || y == 4 || y == 6 || y == 8 || y == 10 || y == 12 || y == 14)) return true;
  if(x == 8 && (y == 1 || y == 3 || y == 5 || y == 7 || y == 9 || y == 11 || y == 13)) return true;
  if(x == 9 && (y == 2 || y == 4 || y == 6 || y == 8 || y == 10 || y == 12)) return true;
  if(x == 10 && (y == 3 || y == 5 || y == 7 || y == 9 || y == 11)) return true;
  if(x == 11 && (y == 4 || y == 6 || y == 8 || y == 10)) return true;
  if(x == 12 && (y == 5 || y == 7 || y == 9)) return true;
  if(x == 13 && (y == 6 || y == 8)) return true;
  if(x == 14 && y == 7) return true;
  return false;
}

void ISR_CHR(void){
  status_cube = STATUS_CHR;
}

//void ISR_IR(void){
//  ir_flag = true;
//}

void charging(void){
  status_leds = LEDS_ON;
  unsigned int pos_x,pos_y,level;
  unsigned int adcvalue = analogRead(PIN_ADC);    //10bit ADC 0-1023
  level = map(adcvalue,613,869,0,14);
  if(digitalRead(PIN_FULL) == LOW){
    for(pos_x = 0;pos_x < 3*15; pos_x ++){
      for(pos_y = 0;pos_y < 15; pos_y ++){
        if(validxy(pos_x,pos_y)) strip.SetPixelColor(xy2pixel(pos_x,pos_y), hslGreen); //cube green to indicate it is fully charged
      }
    }
   
    strip.Show();
    delay(1000);
  for(int i = 0;i<192;i++){
    strip.SetPixelColor(i, black);
  }
  strip.Show();
  delay(1000);
  }
  else{
    //is charging but we want to know the voltage. LiIon should be between 3--613 and 4.2 V--859
    for(pos_y = 0;pos_y < level; pos_y ++){
      for(pos_x = 0;pos_x < 15*3; pos_x ++){
        if(validxy(pos_x,pos_y)) strip.SetPixelColor(xy2pixel(pos_x,pos_y), hslGreen); //cube green to indicate it is fully charged
      }
    }
    strip.Show();
    //delay(500);

  }
}

void turn_off(void){
  for(int i = 0;i<192;i++){
    strip.SetPixelColor(i, black);
    }
  strip.Show();
  status_leds = LEDS_OFF;
}

void status_1(void){  //fill displays in x direction
  status_leds = LEDS_ON;
  unsigned int pos_x; //pos x from 0 to 14 (3x15-1)
  unsigned int pos_y; //pos y from 0 to 14
  // turn off the pixels
  for(int i = 0;i<192 /*&& !ir_flag*/;i++){
    strip.SetPixelColor(i, black);
  }
  strip.Show();
  delay(10);
//pos_y = 8;

  for(pos_y = 0; pos_y < 15 /*&& !ir_flag*/; pos_y ++){
      for(pos_x = 0; pos_x < 15*3 /*&& !ir_flag*/; pos_x ++){
        if(validxy(pos_x,pos_y)){
        strip.SetPixelColor(xy2pixel(pos_x,pos_y), hslGreen);
        strip.Show();
        delay(10);
        }
    }
  }
}

void status_2(void){    //fill display in y direction
  status_leds = LEDS_ON;
  unsigned int pos_x; //pos x from 0 to 14 (3x15-1)
  unsigned int pos_y; //pos y from 0 to 14
  // turn off the pixels
  for(int i = 0;i<192 /*&& !ir_flag*/;i++){
    strip.SetPixelColor(i, black);
  }
  strip.Show();
  delay(10);
//pos_y = 8;

  for(pos_x = 0; pos_x < 15*3 /*&& !ir_flag*/; pos_x ++){
      for(pos_y = 0; pos_y < 15 /*&& !ir_flag*/; pos_y ++){
        if(validxy(pos_x,pos_y)){
        strip.SetPixelColor(xy2pixel(pos_x,pos_y), hslRed);
        strip.Show();
        delay(10);
        }
    }
  }
}

void status_3(void){    //fill display in lines, from botton to top
  status_leds = LEDS_ON;
  unsigned int pos_x; //pos x from 0 to 14 (3x15-1)
  unsigned int pos_y; //pos y from 0 to 14
  // turn off the pixels
  for(int i = 0;i<192 /*&& !ir_flag*/;i++){
    strip.SetPixelColor(i, black);
  }
  strip.Show();
  delay(10);
//pos_y = 8;

  for(pos_y = 0; pos_y < 15 /*&& !ir_flag*/; pos_y ++){
      for(pos_x = 0; pos_x < 15*3 /*&& !ir_flag*/; pos_x ++){
        if(validxy(pos_x,pos_y)){
        strip.SetPixelColor(xy2pixel(pos_x,pos_y), hslBlue);
        }
    }
    strip.Show();
    delay(80);
  }
}

void status_4(void){    //rotate 2 colors in x direction
  status_leds = LEDS_ON;
  unsigned int pos_x; //pos x from 0 to 14 (3x15-1)
  unsigned int pos_y; //pos y from 0 to 14
  // turn off the pixels
//  for(int i = 0;i<192;i++){
//    strip.SetPixelColor(i, black);
//  }
//  strip.Show();
//  delay(1000);
//pos_y = 8;

  for(pos_x = 0; pos_x < 15*3 /*&& !ir_flag*/; pos_x ++){
      for(pos_y = 0; pos_y < 15 /*&& !ir_flag*/; pos_y ++){
        if(validxy(pos_x,pos_y)) strip.SetPixelColor(xy2pixel(pos_x,pos_y), hslBlue);
        if(validxy(pos_x + 1,pos_y)) strip.SetPixelColor(xy2pixel(pos_x + 1,pos_y), hslGreen);
        if(validxy(pos_x + 2,pos_y)) strip.SetPixelColor(xy2pixel(pos_x + 2,pos_y), hslGreen);
        if(validxy(pos_x + 3,pos_y)) strip.SetPixelColor(xy2pixel(pos_x + 3,pos_y), hslGreen);
        if(validxy(pos_x + 4,pos_y)) strip.SetPixelColor(xy2pixel(pos_x + 4,pos_y), hslGreen);
        if(validxy(pos_x + 5,pos_y)) strip.SetPixelColor(xy2pixel(pos_x + 5,pos_y), hslRed);
        if(validxy(pos_x + 6,pos_y)) strip.SetPixelColor(xy2pixel(pos_x + 6,pos_y), hslRed);
        if(validxy(pos_x + 7,pos_y)) strip.SetPixelColor(xy2pixel(pos_x + 7,pos_y), hslRed);
       
    }
    strip.Show();
    delay(80);
  }
}

void status_5(void){    //go up and down
  status_leds = LEDS_ON;
  unsigned int pos_x; //pos x from 0 to 14 (3x15-1)
  unsigned int pos_y; //pos y from 0 to 14
  // turn off the pixels
//  for(int i = 0;i<192;i++){
//    strip.SetPixelColor(i, black);
//  }
//  strip.Show();
//  delay(1000);
//pos_y = 8;

  for(pos_y = 0; pos_y < 15 - 5 /*&& !ir_flag*/; pos_y ++){
      for(pos_x = 0; pos_x < 15*3 /*&& !ir_flag*/; pos_x ++){
        if(validxy(pos_x,pos_y)) strip.SetPixelColor(xy2pixel(pos_x,pos_y), hslYellow);
        if(validxy(pos_x,pos_y + 1)) strip.SetPixelColor(xy2pixel(pos_x,pos_y + 1), hslGreen);
        if(validxy(pos_x,pos_y + 2)) strip.SetPixelColor(xy2pixel(pos_x,pos_y + 2), hslGreen);
        if(validxy(pos_x,pos_y + 3)) strip.SetPixelColor(xy2pixel(pos_x,pos_y + 3), hslGreen);
        if(validxy(pos_x,pos_y + 4)) strip.SetPixelColor(xy2pixel(pos_x,pos_y + 4), hslRed);
        if(validxy(pos_x,pos_y + 5)) strip.SetPixelColor(xy2pixel(pos_x,pos_y + 5), hslRed);  
    }
    strip.Show();
    delay(60);
  }

    for(pos_y = 15; pos_y >= 0 + 5 /*&& !ir_flag*/; pos_y --){
      for(pos_x = 0; pos_x < 15*3 /*&& !ir_flag*/; pos_x ++){
        if(validxy(pos_x,pos_y)) strip.SetPixelColor(xy2pixel(pos_x,pos_y), hslYellow);
        if(validxy(pos_x,pos_y - 1)) strip.SetPixelColor(xy2pixel(pos_x,pos_y - 1), hslGreen);
        if(validxy(pos_x,pos_y - 2)) strip.SetPixelColor(xy2pixel(pos_x,pos_y - 2), hslGreen);
        if(validxy(pos_x,pos_y - 3)) strip.SetPixelColor(xy2pixel(pos_x,pos_y - 3), hslGreen);
        if(validxy(pos_x,pos_y - 4)) strip.SetPixelColor(xy2pixel(pos_x,pos_y - 4), hslRed);
        if(validxy(pos_x,pos_y - 5)) strip.SetPixelColor(xy2pixel(pos_x,pos_y - 5), hslRed);      
    }
    strip.Show();
    delay(60);
  }
}

void status_6(void){
  status_leds = LEDS_ON;
  unsigned int pos_x; //pos x from 0 to 14 (3x15-1)
  unsigned int pos_y; //pos y from 0 to 14
  unsigned int index;
  // turn off the pixels
//  for(int i = 0;i<192;i++){
//    strip.SetPixelColor(i, black);
//  }
//  strip.Show();
//  delay(1000);
//pos_y = 8;

  for(pos_x = 0; pos_x < 15*3 /*&& !ir_flag*/; pos_x ++){
      for(pos_y = 0; pos_y < 15  /*&& !ir_flag*/; pos_y ++){
        for(index = 0; index < 15; index ++){
          if(validxy(pos_x + index,pos_y)) strip.SetPixelColor(xy2pixel((pos_x + index) % (3*15),pos_y), hslRed);
          if(validxy(pos_x + index + 15,pos_y)) strip.SetPixelColor(xy2pixel((pos_x + index + 15) % (3*15),pos_y), hslGreen);
          if(validxy(pos_x + index + 30,pos_y)) strip.SetPixelColor(xy2pixel((pos_x + index + 30) % (3*15),pos_y), hslBlue);
        }
    }
    strip.Show();
    delay(60);
  }
}

void change_mode(void){
  myDecoder.decode();           //Decode SONY protocol
  switch(myDecoder.value){
    case 0x199D: status_cube = STATUS_CHR;break;//DATA CODE
    case 0xD9C: status_cube = STATUS_1;break;//1 REW
    case 0x39C: status_cube = STATUS_2;break;//2 FF
    case 0x19C: status_cube = STATUS_3;break;//3 STOP
    case 0x59C: status_cube = STATUS_4;break;//4 PLAY
    case 0x5BC: status_cube = STATUS_5;break;//5 DATA SCREEN
    case 0x99C: status_cube = STATUS_6;break;//6 PAUSE
    case 0x4C9D: status_cube = STATUS_OFF; break;//START STOP   T is 2C9B and W is 6C9B
    default: status_cube = STATUS_OFF;break;
  }
  //ir_flag = false;
  Serial.print("Status:");
  Serial.println(status_cube);
 
}


void setup()
{
  pinMode(PIN_CHR,INPUT_PULLUP);
  pinMode(PIN_FULL,INPUT_PULLUP);
  //pinMode(PIN_ADC,INPUT);
 
    Serial.begin(115200);
    while (!Serial); // wait for serial attach

    Serial.println();
    Serial.println("Initializing...");
    Serial.flush();

    // this resets all the neopixels to an off state
    strip.Begin();
    strip.Show();

    strip.SetBrightness(brightness);
   
    myReceiver.enableIRIn(); // Start the receiver

    attachInterrupt(digitalPinToInterrupt(PIN_CHR), ISR_CHR, FALLING);
    //attachInterrupt(digitalPinToInterrupt(RECV_PIN), ISR_IR, FALLING);


//    Serial.println();
//    Serial.println("Running...");
}


void loop(){
  if (myReceiver.getResults()) change_mode();
    //Serial.println(results.value, HEX);
  switch(status_cube){
    case STATUS_CHR: /*turn_off();*/ charging();break;
    case STATUS_1: status_1();break;
    case STATUS_2: status_2();break;
    case STATUS_3: status_3();break;
    case STATUS_4: status_4();break;
    case STATUS_5: status_5();break;
    case STATUS_6: status_6();break;
    case STATUS_OFF: if(status_leds == LEDS_ON) turn_off();break;
    default: break;
  }
  myReceiver.enableIRIn();      //Restart receiver
}


Wednesday, April 5, 2017

Programa de prueba para PIC16F628A.

Hola, en este nuevo post os voy a poner un programa de ejemplo para usar con el medidor de frecuencia con PIC16F628A. El entorno de desarrollo que uso es el MPLAB X IDE con compilador XC8.


En primer lugar, aquí podeis descargar el firmware original, para poder restaurar el medidor de frecuencia a su estado original. 

El programa que podeis usar para probar si el medidor se puede reprogramar es muy sencillo, va mostrando numeros en los displays de 7 segmentos. El programa podeis descargarlo aquí.

Si teneis alguna pregunta, no dudeis en ponerla en los comentarios. Hasta la próxima, saludos.



/* 
 * File:   Test_Freq_Counter.c
 * Author: Lenovo_17
 *
 * Created on 1. April 2017, 21:11
 */

// CONFIG
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN)
#pragma config WDTE = OFF        // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
#pragma config BOREN = OFF      // Brown-out Detect Enable bit (BOD disabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>

#define _XTAL_FREQ 20000000


/*RB0 d
  RB1 DP
  RB2 c
  RB3 e
  RB4 f
  RB5 g
  RB6 a
  RB7 b*/

/*RA0 3
  RA1 4
  RA2 2
  RA3 1*/

//PORTB
//#define PIN_A RB6
//#define PIN_B RB7
//#define PIN_C RB2
//#define PIN_D RB0
//#define PIN_E RB3
//#define PIN_F RB4
//#define PIN_G RB5
//#define PIN_DP RB1

#define BIT_A 1 << 6
#define BIT_B 1 << 7
#define BIT_C 1 << 2
#define BIT_D 1 << 0
#define BIT_E 1 << 3
#define BIT_F 1 << 4
#define BIT_G 1 << 5
#define BIT_DP 1 << 1


//#define PIN_D1 RA3
//#define PIN_D2 RA2
//#define PIN_D3 RA0
//#define PIN_D4 RA1

//PORTA 
#define D1 0b00000111;
#define D2 0b00001011;
#define D3 0b00001110;
#define D4 0b00001101;
#define D5 0b00001111;


unsigned char num2seg(unsigned char num){
    unsigned char seg = 0;
    switch(num){
        case 0: seg = BIT_A | BIT_B | BIT_C | BIT_D | BIT_E | BIT_F; break;
        case 1: seg = BIT_B | BIT_C; break;
        case 2: seg = BIT_A | BIT_B | BIT_G | BIT_D | BIT_E; break;
        case 3: seg = BIT_A | BIT_B | BIT_C | BIT_D | BIT_G; break;
        case 4: seg = BIT_B | BIT_C | BIT_G | BIT_F; break;
        case 5: seg = BIT_A | BIT_C | BIT_D | BIT_F | BIT_G; break;
        case 6: seg = BIT_A | BIT_C | BIT_D | BIT_E | BIT_F | BIT_G; break;
        case 7: seg = BIT_A | BIT_B | BIT_C; break;
        case 8: seg = BIT_A | BIT_B | BIT_C | BIT_D | BIT_E | BIT_F | BIT_G; break;
        case 9: seg = BIT_A | BIT_B | BIT_C | BIT_D | BIT_F | BIT_G; break;
        default: seg = BIT_A | BIT_B | BIT_C | BIT_D | BIT_E | BIT_F | BIT_G | BIT_DP; break;
    }
    return seg;
}


void init_ports(void){
    //PINS 12f675 GP0 and GP1 LEDS, Output. GP2 and GP4 keys, input. GP3 Master clear reset. GP4 ADC 
    //ANSEL = 0x58;       // 0b 0101 1000  16TOSC 101 ANS3 SET Analog 0x58 //8Tosc = 001   0x18
    //ADCON0 |= 0x8C;      // 0b 1000 1100   ADFM 1 (right justified ) //VCFG 0 (VDD) //  11 = Channel 03 (AN3 //GP4)  10xx 1100 last 2 bits to start ad conversion
    //ADCON0 = 0b10001101;    //ADON 1, GODone 0
    CMCON = 0x07;
    VRCON = 0x00;
    TRISA &= ~0x0f;  //after reset, trisio register reads all bits as 1
    TRISB = 0x00;
    PORTA |= 0x0f;
    PORTB = 0x00;
    //GPIO = 0x00;    // 0b xxxx xx11     //turn leds off if high 
    
//    INTE = 1;       //activate interrupt in pin 2
//    INTEDG = 0;     //interrupt on falling edge pin 2
//    GIE = 1;        //enable global interrupts
}





//long map(unsigned int x, unsigned int in_min, unsigned int in_max, unsigned int out_min, unsigned int out_max)
//{
//  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
//}

/*
 * 
 */
int main(int argc, char** argv) {
    __delay_ms(1500);   //wait a bit to allow the chip to be reprogrammed. important if you make gp0 and gp1 outputs (pins to programm pic)
    init_ports();
    unsigned char digits[5];// = {D1,D2,D3,D4,D5};
    digits[0] = D1;
    digits[1] = D2;
    digits[2] = D3;
    digits[3] = D4;
    digits[4] = D5;
    unsigned char values[5]= {9,0,1,2,3};
    unsigned long count;
    while(1){
        for(unsigned char j=0;j<10;j++){
            values[0] += 1;
            values[1] += 1;
            values[2] += 1;
            values[3] += 1;
            values[4] += 1;
            count = 0;
            while(count < 30){
            for(unsigned char i = 1; i <= 5  ;i++){
                PORTB = num2seg(values[i-1] % 10);
                PORTA = digits[i-1];
                __delay_ms(4); //50 20 10 5
            }
            count++;
        /*
        for(unsigned char i = 0; i<=9; i++){
        PORTB = num2seg(i);
        PORTA = D1;
        __delay_ms(200);
        PORTA = D2;
        __delay_ms(200);
        PORTA = D3;
        __delay_ms(200);
        PORTA = D4;
        __delay_ms(200);
        PORTA = D5;
        __delay_ms(200);
          */
            }
        }
    }
    return (EXIT_SUCCESS);
}

Sunday, March 12, 2017

Leer y escribir memoria 93CSeries Microwire EEPROM con Arduino.

Bienvenidos a esta nueva entrada. Os pongo el código de arduino para leer y escribir una memoria EEPROM a través del protocolo Microwire, que es una variacion del protocolo SPI.

El sketch de arduino está disponible para su descarga aquí.

Saludos!

/****************************************************
 ********CREATED BY INGENIERIA EN CASA***************
 **********10.03.2016********************************
 *********EEPROM READER/WRITER 93C56 SERIES**********
 ****************************************************
 */

#define PIN_CLK 8   //PIN TO SEND CLOCK SIGNAL
#define PIN_ORG 12  //PIN TO SELECT BYTE OR WORD
#define PIN_S 9     //PIN CHIP SELECT
#define PIN_D 10    //PIN DATA INPUT
#define PIN_Q 11    //PIN DATA OUTPUT

#define MEMORY_SIZE 256   //Size in bytes

byte dataOutput[MEMORY_SIZE];   //variable to store data 

/*shift out 12 bits*/
void shift12bits(unsigned int data){
  digitalWrite(PIN_S,HIGH);       //CHIP SELECT HIGH TO ACTIVATE CHIP
  for(byte count = 0; count < 12; count ++){
    digitalWrite(PIN_CLK,LOW);    //PIN CLOCK LOW TO MAKE AFTER SETTING DATA THE TRANSITION
    if(data & 0x0800)             //MSB FIRST  0x0800 '0b 0000 1000 0000 0000
      digitalWrite(PIN_D,HIGH);
    else 
      digitalWrite(PIN_D,LOW);
    digitalWrite(PIN_CLK,LOW);
    digitalWrite(PIN_CLK,HIGH);   //CLOCK PULSE
    data <<= 1;                   //rotate left to prepare for next bit
  }
}

/*shift out data*/
void shiftdata(byte data_write){
  for(byte count = 0; count < 8; count ++){
    digitalWrite(PIN_CLK,LOW);    //PIN CLOCK LOW TO MAKE AFTER SETTING DATA THE TRANSITION
    if(data_write & 0x80)             //MSB FIRST  0x0800 '0b 0000 1000 0000 0000
      digitalWrite(PIN_D,HIGH);
    else 
      digitalWrite(PIN_D,LOW);
    digitalWrite(PIN_CLK,LOW);
    digitalWrite(PIN_CLK,HIGH);   //CLOCK PULSE
    data_write <<= 1;                   //rotate left to prepare for next bit
  }
}

/*get output from chip*/
void getOutput(byte address_local){
  for(byte i = 0; i < 8; i++){
    digitalWrite(PIN_CLK,LOW);
    digitalWrite(PIN_CLK,HIGH);   //rising edge of clock pin is when data is latched out
    if(digitalRead(PIN_Q))
      dataOutput[address_local] |= 1 << (7-i);  //get msb first. when i = 0, we get 0bX0000000
  }
  digitalWrite(PIN_S,LOW);       //CHIP SELECT LOW TO DEACTIVATE CHIP
}

/*reads the whole memory*/
void read_all(void){
  //start bit = 1
  //read op code = 10
  //Address A8-A0  (A8 not decoded in 93C56WP) 
  //variable address store A7-A0
  unsigned int full_address = 0x0000;
  for(unsigned int address = 0; address < MEMORY_SIZE; address ++){
    full_address = 1 << 11 | 1 << 10 | (byte)address;   //create address with start bit and op code  0b 0000 110X AAAA AAAA
    shift12bits(full_address);
    //while(digitalRead(PIN_Q)){};                  //wait until first dummy 0 is sent by chip
    getOutput(address);
    Serial.print("Adress:");
    Serial.print(address,HEX);
    Serial.print("--");
    Serial.print("Data:");
    Serial.println(dataOutput[address],HEX);
    //delay(50);
  }
}

void write_byte(byte address_write,byte data_write){
  //mask for writing 0b 0000 101X AAAA AAAA
  unsigned int write_mask = 0x0A00 | (byte)address_write;
  shift12bits(write_mask);
  shiftdata(data_write);
  digitalWrite(PIN_S,LOW);                    //CHIP SELECT LOW TO DEACTIVATE CHIP
  digitalWrite(PIN_S,HIGH);                   //BEGIN CHECK STATUS
  while(digitalRead(PIN_Q) == LOW){};         //WAIT UNTIL READY
  digitalWrite(PIN_S,LOW);                    //END CHECK STATUS
  
}

void ew_enable(void){
  unsigned int ew_enable_mask = 0x0980;       //0b0000 1001 1XXX XXXX
  shift12bits(ew_enable_mask);                //send enable write erase mask
  digitalWrite(PIN_S,LOW);                    //CHIP SELECT LOW TO DEACTIVATE CHIP
}

void ew_disable(void){
  unsigned int ew_disable_mask = 0x0800;       //0b0000 1000 0XXX XXXX
  shift12bits(ew_disable_mask);                //send disable write erase mask
  digitalWrite(PIN_S,LOW);                     //CHIP SELECT LOW TO DEACTIVATE CHIP
}

void erase_all(void){
  unsigned int erase_all_mask = 0x0900;       //0b0000 1001 0XXX XXXX
  shift12bits(erase_all_mask);                //send enable write erase mask
  digitalWrite(PIN_S,LOW);                    //CHIP SELECT LOW TO DEACTIVATE CHIP
  digitalWrite(PIN_S,HIGH);                   //BEGIN CHECK STATUS
  while(digitalRead(PIN_Q) == LOW){};         //WAIT UNTIL READY
  digitalWrite(PIN_S,LOW);                    //END CHECK STATUS
}

void setup() {
  // put your setup code here, to run once:
  pinMode(PIN_CLK,OUTPUT);
  pinMode(PIN_ORG,OUTPUT);
  pinMode(PIN_S,OUTPUT);
  pinMode(PIN_D,OUTPUT);
  pinMode(PIN_Q,INPUT);

  digitalWrite(PIN_ORG,LOW);    //ORG = 0 (x8 origination) byte read or write
  digitalWrite(PIN_S,LOW);      //standby state of chip select pin  
  digitalWrite(PIN_CLK,LOW);    //initialize pin clk to low

  Serial.begin(9600);
//  read_all();
//  ew_enable();
//  //erase_all();
//  for(unsigned int counter = 0; counter < MEMORY_SIZE; counter ++)
//  write_byte((byte)counter,MEMORY_SIZE-1-(byte)counter);//write_byte(byte address, byte data);
//  ew_disable();
  read_all();
}

void loop() {
  // put your main code here, to run repeatedly:
}

Sunday, March 5, 2017

Software para pantalla LED.

Bienvenidos a esta nueva entrada. Aquí os dejo las instrucciones para preparar la placa de desarrollo STM32F103C8T6 para que pueda ser reprogramada a través de la conexión usb. También os dejo el software que utilizo en mi propia pantalla LED.

Pasos para preparar la placa STM32 para que se pueda reprogramar por el puerto micro usb:

1. Desoldamos la resistencia pull up resistor R10 de la placa, que tiene el número 103, es decir, es de 10K.
2. Soldamos entre los pines PA12 y 3.3V una resistencia del valor apropiado (1.5K).
Una vez que ya tengamos preparada la placa, podremos proceder a la instalación del bootloader STM32Duino.

Pasos para instalar el bootloader:

1. Descargamos el bootloader correspondiente para nuestra placa. En mi caso, el LED de la placa está conectado al pin PC13, por lo que elegiré el bootloader siguiente: generic_boot20_pc13.bin

Puedes descargar el bootloader correcto para tu placa aquí.

2. Movemos el jumper de BOOT0 a la posicion 1.
3. Conectamos el usb a serie (USB FTDI) con la placa según el siguiente esquema:
    -TX a PA10
    -RX a PA9
    -GND a GND
    -3.3V a 3.3V
Antes  de conectar el convertidor usb a serie, asegúrate de que está configurado para una tensión de salida de 3.3V.
4. Reinicia la placa.
5. Descarga el STM Flash Loader Demostrator de la siguiente web: STM Flash Loader Demostrator Download.
6. Sigue las instrucciones del software.
7. Vuelve a colocar el jumper de BOOT0 en la posición 0.

A partir de ese momento, tu placa STM32 puede ser reprogramada a través del puerto USB.

Espero que os sea de utilidad.

Hasta la próxima.

Bibliografía: stm32duino.com


Desde aquí se puede descargar el software.

Tuesday, February 21, 2017

Mi impresora 3D

Mi impresora 3D

Éste es mi primer post del blog y en él me gustaria describir cómo he construido mi primera impresora 3D.

La idea de construir la impresora surgió un día cuando llegaron a mis manos un par de piezas, unas guias lineales.



Primero decir que el modelo de impresora que yo he construido es único ya que pese a haber muchos modelos diferentes en internet con buenos manuales de montaje, yo quería usar las piezas que tenía a mi alcanze.

Tras elegir el modelo de impresora cartesiana (por ser el que mejor se adaptaba a las piezas que ya tenía), investigué que más piezas me harían falta y si podía utilizar algun componente de los que tuviera por casa. Recopilé las piezas que tenía por casa y compré por internet las que me faltaban.

En la siguiente foto se puede ver la primera prueba, y el resultado de esa impresión: mi primer cubito impreso!



En la siguiente foto se ve el sistema eléctrico de al impresora. Se aprecian los 5 motores paso a paso, y la placa controladora (RAMPS con Arduino).








Aqui se ven las caracteristicas de la correa del eje x (el horizontal). A partir de esos datos se pueden calcular los pasos por mm que se requieren para la configuracion del firmware que controla la impresora (Repetier Firmware).




En este video se puede observar la primera prueba de funcionamiento de la impresora.