2016年7月26日 星期二

74HC595

ref :  http://coopermaa2nd.blogspot.tw/2010/12/arduino-lab12-74hc595-16-led.html



74HC595 是一顆八位元的移位暫存器,同時可以控制八個輸出,我們可以把多顆移位暫存器串接 (Daisy chain) 在一起以擴充腳位,例如: 如果串接兩顆 74HC595 移位暫存器,便可以同時控制 16 個輸出。

74HC595 總共有 16 支接腳,底下這 16 支接腳的圖表說明:


image_thumb4
腳位編號名稱說明
1-7, 15Q0 ~ Q7輸出腳位
8GND接地
7Q7’序列輸出 (Serial Out)
10MRMaster Reset, 清除所有資料, 低電位有效 (Active low)
11SH_CPSHift register clock pin (Clock Pin)
12ST_CPSTorage register clock pin (Latch Pin)
13OEOutput Enable, 允許輸出,低電位有效 (Active low)
14DS序列資料輸入 (Serial data input)
16Vcc供應電壓



步驟一:接上第一顆 74HC595 以及 8 顆 LED
  • 接上 8 顆 LED,將每顆 LED 短腳 (陰極) 直接接到 GND,然後將每顆 LED 的長腳 (陽極) 個別接至 74HC595 的輸出腳位 D0 ~ D7 並串接一顆 220 ohm 電阻
  • 74HC595 接線其一:
    • Vcc (pin 16) 與 MR (pin 10) 接 5V
    • GND (pin 8) 與 OE (pin 13) 接地
  • 74HC595 接線其二:
    • DS (pin 14) 接 Arduino pin 11 (下圖藍線)
    • ST_CP (pin 12, latch pin) 接 Arduino pin 8 (下圖綠線)
    • SH_CP (pin 11, clock pin) 接 Arduino pin 12 (下圖黃線)
  • 假如發現 LED 有震動閃爍的現象,可以在 ST_CP (pin 12, latch pin) 上接一顆 0.1uF 電容以去除閃爍現象
image_thumb21
步驟二:加上第二顆 74HC595,第二顆移位暫存器一樣要接線連到電源與接地
  • Vcc (pin 16) 與 MR (pin 10) 接 5V
  • GND (pin 8) 與 OE (pin 13) 接地
image
步驟三:把兩顆 74HC595 連接起來
只要把第一顆 74HC595 的 SH_CP (Clock Pin) 和 ST_CP (Latch Pin) 兩支腳位接到第二顆 74HC595 上 (下圖中的綠線以及黃線),接著把第一顆 74HC595 的 Q7’ (序列輸出腳) 接到第二顆 74HC595 的 DS (序列資料輸入) 就可以了 (下圖中的藍線)。
image
步驟四:加上第二組 LED
image
電路圖
image
(圖片來源: arduino.cc)
程式碼
底下這支程式 (Shiftout_With_Two_74HC595.pde) 會讓 16 顆 LED 由左往右一顆一顆點亮,實際效果請見範例影片,:
01// Lab12 使用兩顆 74HC595 和三支腳位控制 16 顆 LED
02
03// 接 74HC595 的 ST_CP (pin 12,latch pin)
04int latchPin = 8;
05// 接 74HC595 的 SH_CP (pin 11, clock pin)
06int clockPin = 12;
07// 接 74HC595 的 DS (pin 14)
08int dataPin = 11;
09
10void setup() {
11  // 將 latchPin, clockPin, dataPin 設置為輸出
12  pinMode(latchPin, OUTPUT);
13  pinMode(clockPin, OUTPUT);
14  pinMode(dataPin, OUTPUT);
15}
16
17void loop() {     
18  for (int led = 0; led < 16; led++) {
19    int numberToDisplay  = 1 << led;
20    byte high_Byte = highByte(numberToDisplay);
21    byte low_Byte = lowByte(numberToDisplay);
22     
23    // 送資料前要先把 latchPin 拉成低電位
24    digitalWrite(latchPin, LOW);
25     
26    // 先送高位元組 (Hight Byte), 給離 Arduino 較遠的那顆 74HC595
27    shiftOut(dataPin, clockPin, MSBFIRST, high_Byte); 
28    // 再送低位元組 (Low Byte), 給離 Arduino 較近的那顆 74HC595
29    shiftOut(dataPin, clockPin, MSBFIRST, low_Byte); 
30
31    // 送完資料後要把 latchPin 拉回成高電位
32    digitalWrite(latchPin, HIGH);
33    
34    delay(40);
35  }
36}


因為 shiftOut() 函式一次只能送一個位元組,所以必須將 numberDisplay 拆成兩個位元組分兩次傳送:
1// 先送高位元組 (Hight Byte), 給離 Arduino 較遠的那顆 74HC595
2shiftOut(dataPin, clockPin, MSBFIRST, high_Byte); 
3// 再送低位元組 (Low Byte), 給離 Arduino 較近的那顆 74HC595
4shiftOut(dataPin, clockPin, MSBFIRST, low_Byte); 

再次提醒:在送資料前,記得要先把 latchPin 拉成低電位,緊接著使用 shiftOut() 函式送出資料,送完資料後還要把 latchPin 拉回高電位


shiftOut()


shiftOut()

Description

Shifts out a byte of data one bit at a time. Starts from either the most (i.e. the leftmost) or least (rightmost) significant bit. Each bit is written in turn to a data pin, after which a clock pin is pulsed (taken high, then low) to indicate that the bit is available.
Note: if you're interfacing with a device that's clocked by rising edges, you'll need to make sure that the clock pin is low before the call to shiftOut(), e.g. with a call to digitalWrite(clockPin, LOW).
This is a software implementation; see also the SPI library, which provides a hardware implementation that is faster but works only on specific pins.

Syntax

shiftOut(dataPin, clockPin, bitOrder, value)



2016年7月25日 星期一

pic 18f4620 led example

Ref : https://electrosome.com/led-blinking-pic/



pin  11  和 pin32 要接 vdd

pin  12  和 pin pin31 要接 gnd..

不然就會發生device id 為0 的 case


#include<p18f4550.h>                                                // Include Header for PIC18f455        
  

       /* ******COMPILER DIRECTIVES FOR CHIP CONFIGURATION BITS ***   */
#pragma config PLLDIV = 5 , CPUDIV = OSC1_PLL2 , USBDIV = 2    // You can write this way
// OR
#pragma config FOSC = INTOSCIO_EC
#pragma config FCMEN = OFF                                 // OR this way
#pragma config BORV = 3
#pragma config WDT = OFF
#pragma config CPB = OFF
#pragma config CPD = OFF
/*  ***************  TIMER *************** */
       void delayzz(void)
        {              int i, j;
                        for(i=0;i<5000;i++)
                {
                          for(j=0;j<2;j++)
                      {           /* Well its Just a Timer */            }    }   }
                           
                /* ****************** MAIN ****************** */
      void main(void)
         {
                        TRISB = 0 ;                  // PORT B Setting: Set all the pins in port B to Output.
   
           while(1)
                            {
                                LATBbits.LATB0 = 1;   // RB-1 to High  
                                LATBbits.LATB1 = 1;   // RB-1 to High
                                 delayzz();
                                LATBbits.LATB0 = 0;    // RB-0 to LOW
                                LATBbits.LATB1 = 0;    // RB-0 to LOW
                                 delayzz();
                              }
        }
/* THE END */

Next step is to compile the code.
After the project is built the output files will be dumped into the same project folder, if a separate output folder is not defined for saving all the compiled files.
Now you can use your Programmer to burn the output .hex into the microcontroller.

-Define the header files for pic18f4550.
-Set the Microcontroller configuration settings with “compiler directives”.
-Define PORT settings:- The pins you want to use for blinking. Set the pin to output.
-Then set the timer:- For the time delay in-between the blinks.
-Define Pins to set as ON or OFF with a delay in-between.
-And finally make a loop where the main code will keep executing.

#include


Like most of the programming language first stage is to include/Import header files that we need to define. We are going to code a pic18f4550 hence we are going to include <p18f4550> header that contains all the respective settings and definitions of the microcontroller. 


#Pragma config [Compiler Directive]– Setting the Configuration bits.


Next stage is the pic18f4550 Configuration Bit settings. We need to set the chip configuration, settings for the pic18f4550, which is going to define the Configuration bits for the pic18f4550. For example: whether to use an internal or external oscillator, whether to keep watchdog timer on or off etc. All such settings are handled in Configuration bits setting in the beginning of the code block. If we don’t define the values then the microcontroller will take the default values which might lead to some trouble.
These configuration bits can be assigned with a Compiler directive “#pragma config ”
for example
             #pragma config WDT = ON // watchdog timer on.

For each Configuration Bits, you can write a new line or you can write multiple Chip config bit setting on single #pragma config Directive.
             #pragma config FCMEN = OFF  // Each line with individual setting
             #pragma config IESO = OFFF                             

OR
             #pragma config FCMEN = OFF , IESO = OFFF  //Single line with multiple settings.



You can find the all the Configuration bit settings in the Mplab notes.
-On the top menu on MPLAB IDE click on Help  >>  Topics..  >> PIC18F Config Settings 
-From the left pane go to PIC18F4xxx Configuration Settings and then select PIC18F4550. It would list you all the configuration settings for pic18f4550.

 It would list you all the configuration settings for pic18f4550.

PORT settings: TRISB = 0xF0


IF you want to use any pin in the microcontroller for any operation then you have to first set the pin to either for an input or out put. So you have to define the corresponding PORT to either Input or out put.
  TRISB = 0xF0 ;     // Set pins 7,6,5,4 as input and 3,2,1,0 as Output.
Set pins according to the binary equivalent of the HEX value (0xF0), which is 11110000, Hence first 4 bits from RB0 would be set to output and rest of the pins starting from RB4 would become input.

PORTS

A typical pic18f4550 has 40 pins in it (if it’s a DIP). These 40 pins are divided (classified) into a Logical name PORTS. There are 5 ports in a pic18f4550, PORTB is one of such ports.
Each port is associated with few pins. These ports are accessed by some registersTRISx register is one of such register to access the corresponding port.


TRISB

TRISB Register is used to access port B, which is to define the pins under port B as input or output. Port B has 8 pins, From RB0 to RB7. Check the pin diagram.
For example:
TRISB = 0xF0 ;   // Set pins in Port B  11110000.
Instead of TRISB = 0xF0 ; you can also write
TRISB = 0;
For Setting all the pins in PORTB to input
TRISB = 1;   // Set all the pins in port B to input.



Instead of assigning each pin one by one, you can reduce the coding by defining the entire TRISB to output, only if all the pins are for same purpose.
 Accessing Individual pins
In real time programming there are certain situations where you would want some pins to work as input and some as output in the same PORT.
At such situation you can set individual pins as either input or output.
                TRISBbits.TRISB0 = 0;       //  Set only pin RB0 to output
                TRISBbits.TRISB1 = 1;       //  Set only pin RB1 to Input

In the figure above the pins from same PORTB , RB0-RB3 is set to output, and RB4-RB7 is defined as input. Incase of individual pin settings you have to specifically mention the individual pin.  The pin not defined will be left unused.
TRISB was just an example, same method can be used to gain access to other ports also (PORT A, B, C, D, E). Review the port settings for various Ports and pins associated with them in the datasheet.

void main(void)


The void main is the main section from where the code actually starts to execute. All the function prototypes that are defined outside the main can be called from inside. As like indelayzz() in the code above where we defined it outside the main code block.
The first stage is to Set the port settings, as shown above in PORTS subtopic
The while(1) defined inside is simple endless loop that keep executing the block inside the braces.
For our blinking project we have defined two led's to blink simultaneously together usingLATB Register
                              LATBbits.LATB0 = 1;   // RB-0 to High
                              LATBbits.LATB1 = 1;   // RB-1 to High
                                 delayzz(); // calling the delay function.
                              LATBbits.LATB0 = 0;    // RB-0 to LOW
                              LATBbits.LATB1 = 0;    // RB-1 to LOW

The code can be easily modified to blink alternatively to emit a dipping effect.
          
                             LATBbits.LATB0 = 1;   // RB-0 to High
                             LATBbits.LATB1 = 0;   // RB-1 to LOW
                                 delayzz(); // calling the delay function.
                             LATBbits.LATB0 = 0;    // RB-0 to LOW
                             LATBbits.LATB1 = 1;    // RB-1 to High
                                 delayzz(); // calling the delay function.
For more information Visit my post on PIC18F4550


2.1 Oscillator Types
PIC18F2525/2620/4525/4620 devices can be operated
in ten different oscillator modes. The user can program
the Configuration bits, FOSC3:FOSC0, in Configuration
Register 1H to select one of these ten modes:
1. LP Low-Power Crystal
2. XT Crystal/Resonator
3. HS High-Speed Crystal/Resonator
4. HSPLL High-Speed Crystal/Resonator
with PLL Enabled
5. RC External Resistor/Capacitor with
FOSC/4 Output on RA6
6. RCIO External Resistor/Capacitor with I/O
on RA6
7. INTIO1 Internal Oscillator with FOSC/4 Output
on RA6 and I/O on RA7
8. INTIO2 Internal Oscillator with I/O on RA6
and RA7
9. EC External Clock with FOSC/4 Output
10. ECIO External Clock with I/O on RA6



SYNC BRG16 BRGH
0            0            0                 8-bit/Asynchronous FOSC/[64 (n + 1)]


example :


For a device with FOSC of 16 MHz, desired baud rate of 9600, Asynchronous mode, 8-bit BRG:
Desired Baud Rate = FOSC/(64 ([SPBRGH:SPBRG] + 1))
Solving for SPBRGH:SPBRG:
X = ((FOSC/Desired Baud Rate)/64) – 1
= ((16000000/9600)/64) – 1
= [25.042] = 25
Calculated Baud Rate = 16000000/(64 (25 + 1))
= 9615






INTIO1 Internal Oscillator with FOSC/4 Output
on RA6 and I/O on RA7
8. INTIO2 Internal Oscillator with I/O on RA6
and RA7



Internal Oscillator Block
The PIC18F2525/2620/4525/4620 devices include an
internal oscillator block which generates two different
clock signals; either can be used as the microcontroller’s
clock source. This may eliminate the need for external
oscillator circuits on the OSC1 and/or OSC2 pins.



The main output (INTOSC) is an 8 MHz clock source,
which can be used to directly drive the device clock. It
also drives a postscaler, which can provide a range of
clock frequencies from 31 kHz to 4 MHz. The INTOSC
output is enabled when a clock frequency from 125 kHz
to 8 MHz is selected.


INTIO MODES
Using the internal oscillator as the clock source
eliminates the need for up to two external oscillator
pins, which can then be used for digital I/O. Two distinct
configurations are available:
• In INTIO1 mode, the OSC2 pin outputs FOSC/4,
while OSC1 functions as RA7 for digital input and
output.
• In INTIO2 mode, OSC1 functions as RA7 and
OSC2 functions as RA6, both for digital input and
output.


4 MHz or 8 MHz (OSCCON<6:4> = 111
or 110)




2016年6月20日 星期一



How to find the driver (module) associated with a device on Linux?


udevadm info -a -n /dev/sda | grep -oP 'DRIVERS?=="\K[^"]+' 
sd
ahci

arduino usb2ttl  ->   choose ch341 device driver


Ref : http://unix.stackexchange.com/questions/97676/how-to-find-the-driver-module-associated-with-a-device-on-linux


Have you ever wondered why some USB devices used /dev/ttyUSB0(or 1, or n) and others/dev/ttyACM0 (or 1, or n) when they are plugged into the host computer, while they seem to be acting asUART devices (RS-232-like) over USB in both cases? Have you wondered why example USB firmwares for microcontrollers always end up with names such as /dev/ttyACM0 and never as/dev/ttyUSB0?
Warning: this is a Linux specific post, although it also contains genuine pieces of USB culture.

Ref : https://www.rfc1149.net/blog/2013/03/05/what-is-the-difference-between-devttyusbx-and-devttyacmx/

2016年6月15日 星期三

wifi sample



Hardware board

CC3000





Next, connect the enable and interrupt lines: 
VBEN to Digital 5
 IRQ to Digital 3 

 Now, connect 
 SPI: CLK to Digital 13
 MISO to Digital 12
 MOSI to Digital 11 
 CS to Digital 10


#define WLAN_SSID "myNetwork" // cannot be longer than 32 characters! 
#define WLAN_PASS "myPassword" 
// Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or //WLAN_SEC_WPA2 
#define WLAN_SECURITY WLAN_SEC_WPA2 

// On an UNO, SCK = 13, MISO = 12, and MOSI = 11

//
Adafruit_CC3000(uint8_t csPin, uint8_t irqPin, uint8_t vbatPin, uint8_t spispeed = SPI_CLOCK_DIVIDER);

begin(uint8_t patchReq = 0, bool useSmartConfigData = false);




sample code 如下:


#include <Adafruit_CC3000.h>
#include <SPI.h>
#include "utility/debug.h"
#include "utility/socket.h"

// These are the interrupt and control pins
#define ADAFRUIT_CC3000_IRQ   3  // MUST be an interrupt pin!
// These can be any two pins
#define ADAFRUIT_CC3000_VBAT  5
#define ADAFRUIT_CC3000_CS    10
// Use hardware SPI for the remaining pins
// On an UNO, SCK = 13, MISO = 12, and MOSI = 11
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,
                                         SPI_CLOCK_DIVIDER); // you can change this clock speed

#define WLAN_SSID       "myNetwork"           // cannot be longer than 32 characters!
#define WLAN_PASS       "myPassword"
// Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2
#define WLAN_SECURITY   WLAN_SEC_WPA2

#define LISTEN_PORT           23    // What TCP port to listen on for connections.

Adafruit_CC3000_Server chatServer(LISTEN_PORT);

void setup(void)
{
  Serial.begin(115200);
  Serial.println(F("Hello, CC3000!\n"));

  Serial.print("Free RAM: "); Serial.println(getFreeRam(), DEC);

  /* Initialise the module */
  Serial.println(F("\nInitializing..."));
  if (!cc3000.begin())
  {
    Serial.println(F("Couldn't begin()! Check your wiring?"));
    while(1);
  }

  if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {
    Serial.println(F("Failed!"));
    while(1);
  }
 
  Serial.println(F("Connected!"));

  Serial.println(F("Request DHCP"));
  while (!cc3000.checkDHCP())
  {
    delay(100); // ToDo: Insert a DHCP timeout!
  }

  /* Display the IP address DNS, Gateway, etc. */
  while (! displayConnectionDetails()) {
    delay(1000);
  }

  /*********************************************************/
  /* You can safely remove this to save some flash memory! */
  /*********************************************************/
  Serial.println(F("\r\nNOTE: This sketch may cause problems with other sketches"));
  Serial.println(F("since the .disconnect() function is never called, so the"));
  Serial.println(F("AP may refuse connection requests from the CC3000 until a"));
  Serial.println(F("timeout period passes.  This is normal behaviour since"));
  Serial.println(F("there isn't an obvious moment to disconnect with a server.\r\n"));

  // Start listening for connections
  chatServer.begin();

  Serial.println(F("Listening for connections..."));
}

void loop(void)
{
  // Try to get a client which is connected.
  Adafruit_CC3000_ClientRef client = chatServer.available();
  if (client) {
     // Check if there is data available to read.
     if (client.available() > 0) {
       // Read a byte and write it to all clients.
       uint8_t ch = client.read();
       chatServer.write(ch);
     }
  }
}

/**************************************************************************/
/*!
    @brief  Tries to read the IP address and other connection details
*/
/**************************************************************************/
bool displayConnectionDetails(void)
{
  uint32_t ipAddress, netmask, gateway, dhcpserv, dnsserv;

  if(!cc3000.getIPAddress(&ipAddress, &netmask, &gateway, &dhcpserv, &dnsserv))
  {
    Serial.println(F("Unable to retrieve the IP Address!\r\n"));
    return false;
  }
  else
  {
    Serial.print(F("\nIP Addr: ")); cc3000.printIPdotsRev(ipAddress);
    Serial.print(F("\nNetmask: ")); cc3000.printIPdotsRev(netmask);
    Serial.print(F("\nGateway: ")); cc3000.printIPdotsRev(gateway);
    Serial.print(F("\nDHCPsrv: ")); cc3000.printIPdotsRev(dhcpserv);
    Serial.print(F("\nDNSserv: ")); cc3000.printIPdotsRev(dnsserv);
    Serial.println();
    return true;
  }
}


Ref : https://www.openhacks.com/uploadsproductos/adafruit-cc3000-wifi.pdf

2016年6月13日 星期一

A4988 和 cnc shield 的研究






int dirPin = 8;
 int stepperPin = 7; 
void setup() { 
      pinMode(dirPin, OUTPUT); 
     pinMode(stepperPin, OUTPUT); 
   } 
void step(boolean dir,int steps){ 
digitalWrite(dirPin,dir);
delay(50); 
    for(int i=0;i<steps;i++){ 
        digitalWrite(stepperPin, HIGH); 
        delayMicroseconds(800); 
       digitalWrite(stepperPin, LOW); 
       delayMicroseconds(800); } 
void loop(){
step(true,1600); 
delay(500); 
step(false,1600*5); 
delay(500); } 



Clone X-Axis to the 4th stepper driver(Marked as A)


Use D12 and D13 to drive the 4th stepper driver(Marked as A)



End Stop Configuration
By default GRBL is configured to trigger an alert if an end-stop goes low(Gets grounded).
On the forums this has been much debated and some people requested to have active
High end-stops. The jumpers in the picture provides the option to do both. (To run with
default setting on GRBL the jumper need to be connected like the left shield in the image
below)(This Jumper was only introduced in Version 3.02)

active low -> 左圖...

active high -> 右圖








2016年5月31日 星期二

滾珠的演算法



line : 690 

function solve_board(board, step_callback, finish_callback) {
    var solutions = new Array(ROWS * COLS);
    var weights = get_weights();

    var seed_solution = make_solution(board);
    in_place_evaluate_solution(seed_solution, weights);

    for (var i = 0, s = 0; i < ROWS; ++ i) {
        for (var j = 0; j < COLS; ++ j, ++ s) {
            solutions[s] = copy_solution_with_cursor(seed_solution, i, j);
        }
    }

    var solve_state = {
        step_callback: step_callback,
        finish_callback: finish_callback,
        max_length: get_max_path_length(),
        dir_step: is_8_dir_movement_supported() ? 1 : 2,
        p: 0,
        solutions: solutions,
        weights: weights,
    };

    solve_board_step(solve_state);
}


function copy_solution_with_cursor(solution, i, j, init_cursor) {
    return {board: copy_board(solution.board),
            cursor: make_rc(i, j),
            init_cursor: init_cursor || make_rc(i, j),
            path: solution.path.slice(),
            is_done: solution.is_done,
            weight: 0,
            matches: []};
}