[リストへもどる]   [VBレスキュー(花ちゃん)]
一括表示

投稿時間:2007/05/18(Fri) 11:13
投稿者名:ユウジ
Eメール:
URL :
タイトル:
LED制御について
みなさんはじめまして。

初投稿させていただくユウジと申します。


VB6.0を最近はじめたばかりの初心者です。

ただいま簡素な制御計のプログラムを制作しているのですが初期からいきなりつまずいて

しまいました。


皆様からしたらくだらない質問かもしれませんがお力を貸していただけないでしょうか?




質問:LEDが1〜4まであり
ボタンを押すと1が点灯
もう1度押すと1が消灯し2が点灯
もう1度押すと2が消灯し3が点灯・・・


と言った具合に無限にループするプログラムです。

*********************************************
Dim lRet As Long, bRet(3) As Byte            
        
        lRet = DioInpBit(lHandle, 0, bRet(0))
        lRet = DioInpBit(lHandle, 1, bRet(1))
        lRet = DioInpBit(lHandle, 2, bRet(2))
        lRet = DioInpBit(lHandle, 3, bRet(3))


       'スイッチ1
        If bRet(0) <> 0 Then
           Label1(0).BackColor = &HFF
           lRet = DioOutBit(lHandle, 0, 1)
          
        Else
            Label1(0).BackColor = &H8000000F
        End If



    if bRet(0) = 1 then
           lRet = DioOutBit(lHandle, 0, 0
           lRet = DioOutBit(lHandle, 1 1)
          
        Else
            Label1(0).BackColor = &H8000000F
        End If

        


*********************************************


この条件式だと当然のことながらボタンを押しても

LED1が点灯せずLED2がいきなり点灯してしますます。

参考程度で宜しいのでどのような関数を使えばよいか、

どのような条件でくぎればよいか?

等教えていただけると幸いです。

投稿時間:2007/05/18(Fri) 11:58
投稿者名:ダンボ
Eメール:
URL :
タイトル:
Re: LED制御について
> 質問:LEDが1〜4まであり
> ボタンを押すと1が点灯
> もう1度押すと1が消灯し2が点灯
> もう1度押すと2が消灯し3が点灯・・・
>         lRet = DioInpBit(lHandle, 0, bRet(0))
>         lRet = DioOutBit(lHandle, 0, 1)

面白そうな話題なんですが、DioInpBitとDioOutBitの仕様を説明してください。

特に問題になることは、
・各LEDはS/Wを兼用しているんですね。すなわち対応する4つのS/Wがある。
・bRet(i)が点灯状態を示すのか、あるいはボタンが押されたことを示すのか。
・点灯順番があり、LED1→LED2→LED3→LED4→LED1・・・
・点いているLED1を押すとLED1が消えてLED2が点く。
・点いていないLEDxを押すとLEDxが点く。そのときまで点いていたLEDyは消す。
・無限ループだとするとWaitを入れないとCPU100%になってしまうが良いのか?
 普通は数ミリ秒ごとにS/Wを見るか、S/Wからの割り込みがあるか

これらを整理して素直に表現すればおのずから解決すると思いますよ。
ソースコードも状態表示の部分と操作対応の部分を明確に意識した方が分かりやすい。

投稿時間:2007/05/18(Fri) 12:33
投稿者名:ユウジ
Eメール:
URL :
タイトル:
Re^2: LED制御について
> > 質問:LEDが1〜4まであり
> > ボタンを押すと1が点灯
> > もう1度押すと1が消灯し2が点灯
> > もう1度押すと2が消灯し3が点灯・・・
> >         lRet = DioInpBit(lHandle, 0, bRet(0))
> >         lRet = DioOutBit(lHandle, 0, 1)
>
> 面白そうな話題なんですが、DioInpBitとDioOutBitの仕様を説明してください。
>
> 特に問題になることは、
> ・各LEDはS/Wを兼用しているんですね。すなわち対応する4つのS/Wがある。
> ・bRet(i)が点灯状態を示すのか、あるいはボタンが押されたことを示すのか。
> ・点灯順番があり、LED1→LED2→LED3→LED4→LED1・・・
> ・点いているLED1を押すとLED1が消えてLED2が点く。
> ・点いていないLEDxを押すとLEDxが点く。そのときまで点いていたLEDyは消す。
> ・無限ループだとするとWaitを入れないとCPU100%になってしまうが良いのか?
>  普通は数ミリ秒ごとにS/Wを見るか、S/Wからの割り込みがあるか
>
> これらを整理して素直に表現すればおのずから解決すると思いますよ。
> ソースコードも状態表示の部分と操作対応の部分を明確に意識した方が分かりやすい。


丁寧なお返事ありがとうございます。


DioInpBitとDioOutBitの仕様ですが

******************************************************************************************

Declare Function DioInpBit Lib "ApiDio.DLL" (ByVal hDrv As Long, ByVal InpBitNo As Integer, lpBuf As Byte) As Long


Declare Function DioOutBit Lib "ApiDio.DLL" (ByVal hDrv As Long, ByVal OutBitNo As Integer, ByVal Buf As Byte) As Long

******************************************************************************************

と宣言しています。


ボタンは4つあります。

しかし現時点で使うのは2つで

最初はすべてのLEDが消灯しています。

ボタン1を押すとLED1が点灯

もう1度押すとLED1が消灯し2が点灯する。以後2消灯3点灯・・・の繰り返し。

ボタン2を押すとすべてのLEDが消灯します。


分かりにくい説明で申し訳ない。

投稿時間:2007/05/18(Fri) 13:24
投稿者名:これ
Eメール:
URL :
タイトル:
Re^3: LED制御について
ヨコヤリ失礼します。

手っ取り早く
今どのLEDが点灯してるかを表すポインターの変数(初期値0)を用意して
ボタン1 押す毎に +1 、4超えたら1に戻すようにしておいて
点灯させるときは 一旦全部消してから ポインターに対応したLEDだけを
点ければどうでしょう?
ボタン2を押したらポインターはゼロに戻して。

投稿時間:2007/05/18(Fri) 13:29
投稿者名:ダンボ
Eメール:
URL :
タイトル:
Re^3: LED制御について
箇条書きの質問に答えてもらうと良かったんですが。

> > ・各LEDはS/Wを兼用しているんですね。すなわち対応する4つのS/Wがある。
いいえ。リセットボタンと順次点灯ボタンの2つしかない。


> > ・bRet(i)が点灯状態を示すのか、あるいはボタンが押されたことを示すのか。
回答無し。これがはっきりしないと答えられないかな。DioOutBitはLEDの点灯/消灯を操作する関数のようだが、DioInpBitはLED操作なのLED状態なのかS/W状態なのか?


> > ・点灯順番があり、LED1→LED2→LED3→LED4→LED1・・・
はい。

> > ・点いているLED1を押すとLED1が消えてLED2が点く。
ちょっと違う。「順次点灯ボタンを押すと」


> > ・点いていないLEDxを押すとLEDxが点く。そのときまで点いていたLEDyは消す。
違う。「順次点灯ボタンを押すと」

> > ・無限ループだとするとWaitを入れないとCPU100%になってしまうが良いのか?
> >  普通は数ミリ秒ごとにS/Wを見るか、S/Wからの割り込みがあるか
回答無し。まあCPU100%で良しとして。

投稿時間:2007/05/18(Fri) 16:09
投稿者名:ユウジ
Eメール:
URL :
タイトル:
Re^4: LED制御について
>これさん
親切にありがとうございます。

その方法も試させていただきます。



>ダンボさん
申し訳ありません。

何度も丁寧にありがとうございます。


・各LEDはS/Wを兼用しているんですね。すなわち対応する4つのS/Wがある。
いえ、リセットボタンと順次点灯ボタンの2つのみです。


・bRet(i)が点灯状態を示すのか、あるいはボタンが押されたことを示すのか。
DioInpBitはS/Wの状態です。


・点灯順番があり、LED1→LED2→LED3→LED4→LED1・・・
はい


・点いているLED1を押すとLED1が消えてLED2が点く。
順次ボタンを押すとLED1が消えLED2が点きます。


・点いていないLEDxを押すとLEDxが点く。そのときまで点いていたLEDyは消す。
順次点灯ボタンを押すと順番通りに点き順番通りに消えていきます。


・無限ループだとするとWaitを入れないとCPU100%になってしまうが良いのか?
普通は数ミリ秒ごとにS/Wを見るか、S/Wからの割り込みがあるか

いえ、LED4が点くと順次スイッチは一切受け付けなくなります。
1秒たつと自動的にLED4が消えLED1が点きます。
これの繰り返し処理です。



何度も言いますが無知な自分に親切に教えていただき本当にありがとうございます。

投稿時間:2007/05/18(Fri) 17:02
投稿者名:ダンボ
Eメール:
URL :
タイトル:
Re^5: LED制御について
再確認しますが、現在点いているLEDを調べる関数は無いんですね?
とすれば、これ さんのご指摘のような方法しかやりようが無いでしょう。
(このサブルーチンを呼ぶ方ではWaitを入れないとCPUビジーになることに注意)

Sub CheckAndLight()
Dim lRet As Long, bRet(1) As Byte
Static BitNo As Integer
        
        lRet = DioInpBit(lHandle, 0, bRet(0)) '順次点灯スイッチと仮定する
        lRet = DioInpBit(lHandle, 1, bRet(1)) 'リセットスイッチと仮定する

       'リセットスイッチが押されている場合
        If bRet(1) <> 0 Then BitNo = 0
      
       '順次点灯スイッチが押されている場合
        If bRet(0) <> 0 Then
            Select Case BitNo
            Case 0
                LED1を消す
                LED2を点ける
            Case 1
                LED2を消す
                LED3を点ける
            Case 2
                LED3を消す
                LED4を点ける
            Case 3
                LED4を消す
                LED1を点ける
            End Select
            BitNo = BitNo + 1
            If BitNo > 3 Then BitNo = 0
        End If
End Sub

投稿時間:2007/05/18(Fri) 17:26
投稿者名:ダンボ
Eメール:
URL :
タイトル:
Re^6: LED制御について
ご質問の最初の問題が解決していませんでした。

Sub CheckAndLight()
Dim lRet As Long, bRet(1) As Byte
Static BitNo As Integer
        
        lRet = DioInpBit(lHandle, 0, bRet(0)) '順次点灯スイッチと仮定する
        lRet = DioInpBit(lHandle, 1, bRet(1)) 'リセットスイッチと仮定する

       'リセットスイッチが押されている場合
        If bRet(1) <> 0 Then BitNo = 0
      
       '順次点灯スイッチが押されている場合
        If bRet(0) <> 0 Then
            Select Case BitNo
            Case 0
                LED1を点ける
            Case 1
                LED1を消す
                LED2を点ける
            Case 2
                LED2を消す
                LED3を点ける
            Case 3
                LED3を消す
                LED4を点ける
            Case 4
                LED4を消す
                LED1を点ける
            End Select
            BitNo = BitNo + 1
            If BitNo > 4 Then BitNo = 1
        End If
End Sub

投稿時間:2007/05/18(Fri) 17:33
投稿者名:ユウジ
Eメール:
URL :
タイトル:
Re^6: LED制御について
> 再確認しますが、現在点いているLEDを調べる関数は無いんですね?
> とすれば、これ さんのご指摘のような方法しかやりようが無いでしょう。
> (このサブルーチンを呼ぶ方ではWaitを入れないとCPUビジーになることに注意)
>
> Sub CheckAndLight()
>  Dim lRet As Long, bRet(1) As Byte
>  Static BitNo As Integer
>        
>         lRet = DioInpBit(lHandle, 0, bRet(0)) '順次点灯スイッチと仮定する
>         lRet = DioInpBit(lHandle, 1, bRet(1)) 'リセットスイッチと仮定する
>
>        'リセットスイッチが押されている場合
>         If bRet(1) <> 0 Then BitNo = 0
>        
>        '順次点灯スイッチが押されている場合
>         If bRet(0) <> 0 Then
>             Select Case BitNo
>             Case 0
>                 LED1を消す
>                 LED2を点ける
>             Case 1
>                 LED2を消す
>                 LED3を点ける
>             Case 2
>                 LED3を消す
>                 LED4を点ける
>             Case 3
>                 LED4を消す
>                 LED1を点ける
>             End Select
>             BitNo = BitNo + 1
>             If BitNo > 3 Then BitNo = 0
>         End If
> End Sub


> 再確認しますが、現在点いているLEDを調べる関数は無いんですね?
はい、申し訳ありませんがありません。

そしてソースありがとうございます!

早速試させていただきます。

投稿時間:2007/05/21(Mon) 11:41
投稿者名:y4yama
Eメール:
URL :
タイトル:
Re^7: LED制御について
よこレス申し訳ありません。
> いえ、リセットボタンと順次点灯ボタンの2つのみです。
> ・bRet(i)が点灯状態を示すのか、あるいはボタンが押されたことを示すのか。
> DioInpBitはS/Wの状態です。

「S/Wの状態」ということは、今ONかOFFかが判定できるだけですネ?
だったら、順次点灯ボタンが押されて、放されて、の後でないと、次に押されたという
判断は不可能です。今までにOFFであるから今ONされた、という判断をしないと、すぐにLED4が点くとこまでいってしまうような気がします
それと、通常のスイッチはチャタリングがあるので、ONになってから0.1秒の間はつぎの
ONがあっても無視する、というような考慮が必要です

今回は多分不要ですが(もし私の想像したメーカのだったら)マニュアルによると、
出力ポートの状態は検知できますネ
■説明
出力ポートの状態を1ビット入力します。出力データは0か1で返ります。
出力されている内容をモニタする場合に使用します。
■使用例
VB  Ret = DioEchoBackBit(Id, BitNo, Data)


以上、参考になれば幸いデス

投稿時間:2007/05/21(Mon) 18:41
投稿者名:ユウジ
Eメール:
URL :
タイトル:
Re^8: LED制御について
お返事とお礼が遅れてしまいました。申し訳ないです。

>ダンボさん
前回のソースと知識の提供、ありがとうございました。

とても参考になりました。現在Timerやチャタリングについて勉強中です。
(笑われるかもしれませんが自分はまだその程度です)



>y4yamaさん
ご親切にありがとうございます。

助言のほう参考にさせていただきます。

はい、確かに押しっぱなしですといっきに1→2→→3→4→1・・・・と永遠に繰り返してしまします。

> 今回は多分不要ですが(もし私の想像したメーカのだったら)マニュアルによると、
> 出力ポートの状態は検知できますネ
CONT○Cさん製のを使用しております。

投稿時間:2007/05/22(Tue) 12:01
投稿者名:ユウジ
Eメール:
URL :
タイトル:
Re^9: LED制御について
どうしてもチャタリング対策の仕方が分かりません。

助言頂けると幸いです。

以下のソースで(スイッチが4個→8個になりました)LEDを点けて

ボタンを押すごとに(押しっぱなしでも)LED1→8へと一瞬で点き

LED8→LED1に一瞬で戻って押しっぱなしだと永遠にループしてしまいます。


どこにどのようにして「wait,waittimer」を入れれば宜しいのでしょうか?

自分でもかなり実験したのですが分からず仕舞でしたので・・・

ご迷惑かもしれませんが助言いただけないでしょうか?



Private Sub Timer1_Timer()

        Dim lRet As Long, bRet(3) As Byte
        Static BitNo As Integer
    
        lRet = DioInpBit(lHandle, 0, bRet(0)) '**順次点灯スイッチ
        lRet = DioInpBit(lHandle, 1, bRet(1)) '**リセットスイッチ
        lRet = DioInpBit(lHandle, 2, bRet(2)) '**まだ使わないスイッチ
        lRet = DioInpBit(lHandle, 3, bRet(3)) '**まだ使わないスイッチ
      
       '**順次点灯スイッチ押した場合(スイッチ1)
        If bRet(0) <> 0 Then
            Label1(0).BackColor = &HFF
            Select Case BitNo
            Case 0
                '**LED1を点ける
                 lRet = DioOutBit(lHandle, 0, 1)
                 '**LED8を消す
                 lRet = DioOutBit(lHandle, 7, 0)
            Case 1
                '**LED1を消す
                 lRet = DioOutBit(lHandle, 0, 0)
                '**LED2を点ける
                 lRet = DioOutBit(lHandle, 1, 1)
            Case 2
                '**LED2を消す
                 lRet = DioOutBit(lHandle, 1, 0)
                '**LED3を点ける
                 lRet = DioOutBit(lHandle, 2, 1)
            Case 3
                '**LED3を消す
                 lRet = DioOutBit(lHandle, 2, 0)
                '**LED4を点ける
                 lRet = DioOutBit(lHandle, 3, 1)
            Case 4
                '**LED4を消す
                 lRet = DioOutBit(lHandle, 3, 0)
                '**LED5を点ける
                 lRet = DioOutBit(lHandle, 4, 1)
            Case 5
                '**LED5を消す
                 lRet = DioOutBit(lHandle, 4, 0)
                '**LED6を点ける
                 lRet = DioOutBit(lHandle, 5, 1)
            Case 6
                '**LED6を消す
                 lRet = DioOutBit(lHandle, 5, 0)
                '**LED7を点ける
                 lRet = DioOutBit(lHandle, 6, 1)
            Case 7
                '**LED7を消す
                 lRet = DioOutBit(lHandle, 6, 0)
                '**LED8を点ける
                 lRet = DioOutBit(lHandle, 7, 1)
                
                
                
            End Select
                BitNo = BitNo + 1
          
            If BitNo > 7 Then
                BitNo = 0
            End If
            Else
                Label1(0).BackColor = &H8000000F
        End If
        
        '**リセットスイッチ押した場合(スイッチ2)
        If bRet(1) <> 0 Then
            Label1(1).BackColor = &HFF
            lRet = DioOutBit(lHandle, 0, 0)
            lRet = DioOutBit(lHandle, 1, 0)
            lRet = DioOutBit(lHandle, 2, 0)
            lRet = DioOutBit(lHandle, 3, 0)
            lRet = DioOutBit(lHandle, 4, 0)
            lRet = DioOutBit(lHandle, 5, 0)
            lRet = DioOutBit(lHandle, 6, 0)
            lRet = DioOutBit(lHandle, 7, 0)
            BitNo = 0
        Else
            Label1(1).BackColor = &H8000000F
        End If
        
      
        '**スイッチ3(使わない
        If bRet(2) <> 0 Then
            Label1(2).BackColor = &HFF
        Else
            Label1(2).BackColor = &H8000000F
        End If
      
        '**スイッチ4(使わない
        If bRet(3) <> 0 Then
            Label1(3).BackColor = &HFF
        Else
            Label1(3).BackColor = &H8000000F
            
        End If
        End Sub

投稿時間:2007/05/22(Tue) 14:40
投稿者名:ダンボ
Eメール:
URL :
タイトル:
Re^10: LED制御について
> ボタンを押すごとに(押しっぱなしでも)LED1→8へと一瞬で点き
> LED8→LED1に一瞬で戻って押しっぱなしだと永遠にループしてしまいます。

だからWait入れろって言ったのに(笑)
下記WaitルーチンはK.J.K.さんからの流用です。
注1.メインは無限ループなので停める手続きを考えておいた方が良い。
注2.No.9177 でなくてNo.9176 のほうのサンプルを下書きにしたようだがいいの?
注3.チャタリング対策していません。
 チャタリング?ハードウェアの方で実装すべきものでは?(とハード屋と喧嘩するソフト屋)

Option Explicit
Private Declare Function MsgWaitForMultipleObjects Lib "user32.dll" _
(Optional ByVal Count As Long = 0&, _
Optional ByVal HandlesPointer As Long = 0&, _
Optional ByVal WaitAll As Long = 0&, _
Optional ByVal Milliseconds As Long = 0&, _
Optional ByVal WakeMask As Long = &HFF&) As Long
Private Declare Function GetTickCount Lib "kernel32.dll" () As Long

Private Sub Wait(WaitTime As Long)
    Dim iStart As Long, iInterval As Long

    iStart = GetTickCount()
    iInterval = WaitTime
    Do
        If 0& = MsgWaitForMultipleObjects(, , , iInterval) _
            Then DoEvents
        iInterval = WaitTime - GetTickCount() + iStart
    Loop While (iInterval >= 0&)
End Sub

Private Sub Form_Load()
    Do
        Call CheckAndLight()
        Call Wait(10)
        DoEvents
    Loop
End Sub

投稿時間:2007/05/22(Tue) 14:53
投稿者名:y4yama
Eメール:
URL :
タイトル:
Re^11: LED制御について
ウェイトについては、No.9195では、
  Private Sub Timer1_Timer()
となってますから、interval を 300〜1000かにしとけば、解決カナ?と思いました
まぁ、メカトロの実習が終わったようなので、言及してもしかたないかぁ・・・

投稿時間:2007/05/23(Wed) 10:41
投稿者名:ふく
Eメール:
URL :
タイトル:
Re: LED制御について
横やりすみません。
プログラム以前の問題かと…

入力と出力との関係を整理する必要があると思います。

たとえば、
スイッチを押す動作には2つの状態変化があります。
1、OFF→ON  押した
2、ON→OFF  離した
入力の状態変化に対して、出力の状態はどうなるのか

紙の上に箇条書きで順番に書くことがコツです。
この辺を整理すればプログラムは単純になりますよ。

それと
コンテックのボードを使用しているようですが、
出力の状態を調べる関数もあります。
デジタル入出力のサンプルプログラム内にその関数を使用しています。